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 #define LOG_TAG "InputConsumerNoResampling"
18*38e8c45fSAndroid Build Coastguard Worker #define ATRACE_TAG ATRACE_TAG_INPUT
19*38e8c45fSAndroid Build Coastguard Worker
20*38e8c45fSAndroid Build Coastguard Worker #include <inttypes.h>
21*38e8c45fSAndroid Build Coastguard Worker
22*38e8c45fSAndroid Build Coastguard Worker #include <android-base/logging.h>
23*38e8c45fSAndroid Build Coastguard Worker #include <android-base/properties.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <cutils/properties.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <ftl/enum.h>
27*38e8c45fSAndroid Build Coastguard Worker #include <utils/Trace.h>
28*38e8c45fSAndroid Build Coastguard Worker
29*38e8c45fSAndroid Build Coastguard Worker #include <com_android_input_flags.h>
30*38e8c45fSAndroid Build Coastguard Worker #include <input/InputConsumerNoResampling.h>
31*38e8c45fSAndroid Build Coastguard Worker #include <input/PrintTools.h>
32*38e8c45fSAndroid Build Coastguard Worker #include <input/TraceTools.h>
33*38e8c45fSAndroid Build Coastguard Worker
34*38e8c45fSAndroid Build Coastguard Worker namespace android {
35*38e8c45fSAndroid Build Coastguard Worker
36*38e8c45fSAndroid Build Coastguard Worker namespace {
37*38e8c45fSAndroid Build Coastguard Worker
38*38e8c45fSAndroid Build Coastguard Worker using std::chrono::nanoseconds;
39*38e8c45fSAndroid Build Coastguard Worker
40*38e8c45fSAndroid Build Coastguard Worker using android::base::Result;
41*38e8c45fSAndroid Build Coastguard Worker
42*38e8c45fSAndroid Build Coastguard Worker /**
43*38e8c45fSAndroid Build Coastguard Worker * Log debug messages relating to the consumer end of the transport channel.
44*38e8c45fSAndroid Build Coastguard Worker * Enable this via "adb shell setprop log.tag.InputTransportConsumer DEBUG" (requires restart)
45*38e8c45fSAndroid Build Coastguard Worker */
46*38e8c45fSAndroid Build Coastguard Worker const bool DEBUG_TRANSPORT_CONSUMER =
47*38e8c45fSAndroid Build Coastguard Worker __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Consumer", ANDROID_LOG_INFO);
48*38e8c45fSAndroid Build Coastguard Worker
createKeyEvent(const InputMessage & msg)49*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<KeyEvent> createKeyEvent(const InputMessage& msg) {
50*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<KeyEvent> event = std::make_unique<KeyEvent>();
51*38e8c45fSAndroid Build Coastguard Worker event->initialize(msg.body.key.eventId, msg.body.key.deviceId, msg.body.key.source,
52*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId{msg.body.key.displayId}, msg.body.key.hmac,
53*38e8c45fSAndroid Build Coastguard Worker msg.body.key.action, msg.body.key.flags, msg.body.key.keyCode,
54*38e8c45fSAndroid Build Coastguard Worker msg.body.key.scanCode, msg.body.key.metaState, msg.body.key.repeatCount,
55*38e8c45fSAndroid Build Coastguard Worker msg.body.key.downTime, msg.body.key.eventTime);
56*38e8c45fSAndroid Build Coastguard Worker return event;
57*38e8c45fSAndroid Build Coastguard Worker }
58*38e8c45fSAndroid Build Coastguard Worker
createFocusEvent(const InputMessage & msg)59*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<FocusEvent> createFocusEvent(const InputMessage& msg) {
60*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<FocusEvent> event = std::make_unique<FocusEvent>();
61*38e8c45fSAndroid Build Coastguard Worker event->initialize(msg.body.focus.eventId, msg.body.focus.hasFocus);
62*38e8c45fSAndroid Build Coastguard Worker return event;
63*38e8c45fSAndroid Build Coastguard Worker }
64*38e8c45fSAndroid Build Coastguard Worker
createCaptureEvent(const InputMessage & msg)65*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<CaptureEvent> createCaptureEvent(const InputMessage& msg) {
66*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<CaptureEvent> event = std::make_unique<CaptureEvent>();
67*38e8c45fSAndroid Build Coastguard Worker event->initialize(msg.body.capture.eventId, msg.body.capture.pointerCaptureEnabled);
68*38e8c45fSAndroid Build Coastguard Worker return event;
69*38e8c45fSAndroid Build Coastguard Worker }
70*38e8c45fSAndroid Build Coastguard Worker
createDragEvent(const InputMessage & msg)71*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<DragEvent> createDragEvent(const InputMessage& msg) {
72*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<DragEvent> event = std::make_unique<DragEvent>();
73*38e8c45fSAndroid Build Coastguard Worker event->initialize(msg.body.drag.eventId, msg.body.drag.x, msg.body.drag.y,
74*38e8c45fSAndroid Build Coastguard Worker msg.body.drag.isExiting);
75*38e8c45fSAndroid Build Coastguard Worker return event;
76*38e8c45fSAndroid Build Coastguard Worker }
77*38e8c45fSAndroid Build Coastguard Worker
createMotionEvent(const InputMessage & msg)78*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<MotionEvent> createMotionEvent(const InputMessage& msg) {
79*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<MotionEvent> event = std::make_unique<MotionEvent>();
80*38e8c45fSAndroid Build Coastguard Worker const uint32_t pointerCount = msg.body.motion.pointerCount;
81*38e8c45fSAndroid Build Coastguard Worker std::vector<PointerProperties> pointerProperties;
82*38e8c45fSAndroid Build Coastguard Worker pointerProperties.reserve(pointerCount);
83*38e8c45fSAndroid Build Coastguard Worker std::vector<PointerCoords> pointerCoords;
84*38e8c45fSAndroid Build Coastguard Worker pointerCoords.reserve(pointerCount);
85*38e8c45fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < pointerCount; i++) {
86*38e8c45fSAndroid Build Coastguard Worker pointerProperties.push_back(msg.body.motion.pointers[i].properties);
87*38e8c45fSAndroid Build Coastguard Worker pointerCoords.push_back(msg.body.motion.pointers[i].coords);
88*38e8c45fSAndroid Build Coastguard Worker }
89*38e8c45fSAndroid Build Coastguard Worker
90*38e8c45fSAndroid Build Coastguard Worker ui::Transform transform;
91*38e8c45fSAndroid Build Coastguard Worker transform.set({msg.body.motion.dsdx, msg.body.motion.dtdx, msg.body.motion.tx,
92*38e8c45fSAndroid Build Coastguard Worker msg.body.motion.dtdy, msg.body.motion.dsdy, msg.body.motion.ty, 0, 0, 1});
93*38e8c45fSAndroid Build Coastguard Worker ui::Transform displayTransform;
94*38e8c45fSAndroid Build Coastguard Worker displayTransform.set({msg.body.motion.dsdxRaw, msg.body.motion.dtdxRaw, msg.body.motion.txRaw,
95*38e8c45fSAndroid Build Coastguard Worker msg.body.motion.dtdyRaw, msg.body.motion.dsdyRaw, msg.body.motion.tyRaw,
96*38e8c45fSAndroid Build Coastguard Worker 0, 0, 1});
97*38e8c45fSAndroid Build Coastguard Worker event->initialize(msg.body.motion.eventId, msg.body.motion.deviceId, msg.body.motion.source,
98*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId{msg.body.motion.displayId}, msg.body.motion.hmac,
99*38e8c45fSAndroid Build Coastguard Worker msg.body.motion.action, msg.body.motion.actionButton, msg.body.motion.flags,
100*38e8c45fSAndroid Build Coastguard Worker msg.body.motion.edgeFlags, msg.body.motion.metaState,
101*38e8c45fSAndroid Build Coastguard Worker msg.body.motion.buttonState, msg.body.motion.classification, transform,
102*38e8c45fSAndroid Build Coastguard Worker msg.body.motion.xPrecision, msg.body.motion.yPrecision,
103*38e8c45fSAndroid Build Coastguard Worker msg.body.motion.xCursorPosition, msg.body.motion.yCursorPosition,
104*38e8c45fSAndroid Build Coastguard Worker displayTransform, msg.body.motion.downTime, msg.body.motion.eventTime,
105*38e8c45fSAndroid Build Coastguard Worker pointerCount, pointerProperties.data(), pointerCoords.data());
106*38e8c45fSAndroid Build Coastguard Worker return event;
107*38e8c45fSAndroid Build Coastguard Worker }
108*38e8c45fSAndroid Build Coastguard Worker
addSample(MotionEvent & event,const InputMessage & msg)109*38e8c45fSAndroid Build Coastguard Worker void addSample(MotionEvent& event, const InputMessage& msg) {
110*38e8c45fSAndroid Build Coastguard Worker uint32_t pointerCount = msg.body.motion.pointerCount;
111*38e8c45fSAndroid Build Coastguard Worker std::vector<PointerCoords> pointerCoords;
112*38e8c45fSAndroid Build Coastguard Worker pointerCoords.reserve(pointerCount);
113*38e8c45fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < pointerCount; i++) {
114*38e8c45fSAndroid Build Coastguard Worker pointerCoords.push_back(msg.body.motion.pointers[i].coords);
115*38e8c45fSAndroid Build Coastguard Worker }
116*38e8c45fSAndroid Build Coastguard Worker
117*38e8c45fSAndroid Build Coastguard Worker // TODO(b/329770983): figure out if it's safe to combine events with mismatching metaState
118*38e8c45fSAndroid Build Coastguard Worker event.setMetaState(event.getMetaState() | msg.body.motion.metaState);
119*38e8c45fSAndroid Build Coastguard Worker event.addSample(msg.body.motion.eventTime, pointerCoords.data(), msg.body.motion.eventId);
120*38e8c45fSAndroid Build Coastguard Worker }
121*38e8c45fSAndroid Build Coastguard Worker
createTouchModeEvent(const InputMessage & msg)122*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<TouchModeEvent> createTouchModeEvent(const InputMessage& msg) {
123*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<TouchModeEvent> event = std::make_unique<TouchModeEvent>();
124*38e8c45fSAndroid Build Coastguard Worker event->initialize(msg.body.touchMode.eventId, msg.body.touchMode.isInTouchMode);
125*38e8c45fSAndroid Build Coastguard Worker return event;
126*38e8c45fSAndroid Build Coastguard Worker }
127*38e8c45fSAndroid Build Coastguard Worker
outboundMessageToString(const InputMessage & outboundMsg)128*38e8c45fSAndroid Build Coastguard Worker std::string outboundMessageToString(const InputMessage& outboundMsg) {
129*38e8c45fSAndroid Build Coastguard Worker switch (outboundMsg.header.type) {
130*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::FINISHED: {
131*38e8c45fSAndroid Build Coastguard Worker return android::base::StringPrintf(" Finish: seq=%" PRIu32 " handled=%s",
132*38e8c45fSAndroid Build Coastguard Worker outboundMsg.header.seq,
133*38e8c45fSAndroid Build Coastguard Worker toString(outboundMsg.body.finished.handled));
134*38e8c45fSAndroid Build Coastguard Worker }
135*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::TIMELINE: {
136*38e8c45fSAndroid Build Coastguard Worker return android::base::
137*38e8c45fSAndroid Build Coastguard Worker StringPrintf(" Timeline: inputEventId=%" PRId32 " gpuCompletedTime=%" PRId64
138*38e8c45fSAndroid Build Coastguard Worker ", presentTime=%" PRId64,
139*38e8c45fSAndroid Build Coastguard Worker outboundMsg.body.timeline.eventId,
140*38e8c45fSAndroid Build Coastguard Worker outboundMsg.body.timeline
141*38e8c45fSAndroid Build Coastguard Worker .graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME],
142*38e8c45fSAndroid Build Coastguard Worker outboundMsg.body.timeline
143*38e8c45fSAndroid Build Coastguard Worker .graphicsTimeline[GraphicsTimeline::PRESENT_TIME]);
144*38e8c45fSAndroid Build Coastguard Worker }
145*38e8c45fSAndroid Build Coastguard Worker default: {
146*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << "Outbound message must be FINISHED or TIMELINE, got "
147*38e8c45fSAndroid Build Coastguard Worker << ftl::enum_string(outboundMsg.header.type);
148*38e8c45fSAndroid Build Coastguard Worker return "Unreachable";
149*38e8c45fSAndroid Build Coastguard Worker }
150*38e8c45fSAndroid Build Coastguard Worker }
151*38e8c45fSAndroid Build Coastguard Worker }
152*38e8c45fSAndroid Build Coastguard Worker
createFinishedMessage(uint32_t seq,bool handled,nsecs_t consumeTime)153*38e8c45fSAndroid Build Coastguard Worker InputMessage createFinishedMessage(uint32_t seq, bool handled, nsecs_t consumeTime) {
154*38e8c45fSAndroid Build Coastguard Worker InputMessage msg;
155*38e8c45fSAndroid Build Coastguard Worker msg.header.type = InputMessage::Type::FINISHED;
156*38e8c45fSAndroid Build Coastguard Worker msg.header.seq = seq;
157*38e8c45fSAndroid Build Coastguard Worker msg.body.finished.handled = handled;
158*38e8c45fSAndroid Build Coastguard Worker msg.body.finished.consumeTime = consumeTime;
159*38e8c45fSAndroid Build Coastguard Worker return msg;
160*38e8c45fSAndroid Build Coastguard Worker }
161*38e8c45fSAndroid Build Coastguard Worker
createTimelineMessage(int32_t inputEventId,nsecs_t gpuCompletedTime,nsecs_t presentTime)162*38e8c45fSAndroid Build Coastguard Worker InputMessage createTimelineMessage(int32_t inputEventId, nsecs_t gpuCompletedTime,
163*38e8c45fSAndroid Build Coastguard Worker nsecs_t presentTime) {
164*38e8c45fSAndroid Build Coastguard Worker InputMessage msg;
165*38e8c45fSAndroid Build Coastguard Worker msg.header.type = InputMessage::Type::TIMELINE;
166*38e8c45fSAndroid Build Coastguard Worker msg.header.seq = 0;
167*38e8c45fSAndroid Build Coastguard Worker msg.body.timeline.eventId = inputEventId;
168*38e8c45fSAndroid Build Coastguard Worker msg.body.timeline.graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = gpuCompletedTime;
169*38e8c45fSAndroid Build Coastguard Worker msg.body.timeline.graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = presentTime;
170*38e8c45fSAndroid Build Coastguard Worker return msg;
171*38e8c45fSAndroid Build Coastguard Worker }
172*38e8c45fSAndroid Build Coastguard Worker
operator <<(std::ostream & out,const InputMessage & msg)173*38e8c45fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& out, const InputMessage& msg) {
174*38e8c45fSAndroid Build Coastguard Worker out << ftl::enum_string(msg.header.type);
175*38e8c45fSAndroid Build Coastguard Worker return out;
176*38e8c45fSAndroid Build Coastguard Worker }
177*38e8c45fSAndroid Build Coastguard Worker
178*38e8c45fSAndroid Build Coastguard Worker } // namespace
179*38e8c45fSAndroid Build Coastguard Worker
180*38e8c45fSAndroid Build Coastguard Worker // --- InputConsumerNoResampling ---
181*38e8c45fSAndroid Build Coastguard Worker
InputConsumerNoResampling(const std::shared_ptr<InputChannel> & channel,sp<Looper> looper,InputConsumerCallbacks & callbacks,std::function<std::unique_ptr<Resampler> ()> resamplerCreator)182*38e8c45fSAndroid Build Coastguard Worker InputConsumerNoResampling::InputConsumerNoResampling(
183*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<InputChannel>& channel, sp<Looper> looper,
184*38e8c45fSAndroid Build Coastguard Worker InputConsumerCallbacks& callbacks,
185*38e8c45fSAndroid Build Coastguard Worker std::function<std::unique_ptr<Resampler>()> resamplerCreator)
186*38e8c45fSAndroid Build Coastguard Worker : mChannel{channel},
187*38e8c45fSAndroid Build Coastguard Worker mLooper{looper},
188*38e8c45fSAndroid Build Coastguard Worker mCallbacks{callbacks},
189*38e8c45fSAndroid Build Coastguard Worker mResamplerCreator{std::move(resamplerCreator)},
190*38e8c45fSAndroid Build Coastguard Worker mFdEvents(0) {
191*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mLooper == nullptr);
192*38e8c45fSAndroid Build Coastguard Worker mCallback = sp<LooperEventCallback>::make(
193*38e8c45fSAndroid Build Coastguard Worker std::bind(&InputConsumerNoResampling::handleReceiveCallback, this,
194*38e8c45fSAndroid Build Coastguard Worker std::placeholders::_1));
195*38e8c45fSAndroid Build Coastguard Worker // In the beginning, there are no pending outbounds events; we only care about receiving
196*38e8c45fSAndroid Build Coastguard Worker // incoming data.
197*38e8c45fSAndroid Build Coastguard Worker setFdEvents(ALOOPER_EVENT_INPUT);
198*38e8c45fSAndroid Build Coastguard Worker }
199*38e8c45fSAndroid Build Coastguard Worker
~InputConsumerNoResampling()200*38e8c45fSAndroid Build Coastguard Worker InputConsumerNoResampling::~InputConsumerNoResampling() {
201*38e8c45fSAndroid Build Coastguard Worker ensureCalledOnLooperThread(__func__);
202*38e8c45fSAndroid Build Coastguard Worker // If there are any remaining unread batches, send an ack for them and don't deliver
203*38e8c45fSAndroid Build Coastguard Worker // them to callbacks.
204*38e8c45fSAndroid Build Coastguard Worker for (auto& [_, batches] : mBatches) {
205*38e8c45fSAndroid Build Coastguard Worker while (!batches.empty()) {
206*38e8c45fSAndroid Build Coastguard Worker finishInputEvent(batches.front().header.seq, /*handled=*/false);
207*38e8c45fSAndroid Build Coastguard Worker batches.pop();
208*38e8c45fSAndroid Build Coastguard Worker }
209*38e8c45fSAndroid Build Coastguard Worker }
210*38e8c45fSAndroid Build Coastguard Worker
211*38e8c45fSAndroid Build Coastguard Worker while (!mOutboundQueue.empty()) {
212*38e8c45fSAndroid Build Coastguard Worker processOutboundEvents();
213*38e8c45fSAndroid Build Coastguard Worker // This is our last chance to ack the events. If we don't ack them here, we will get an ANR,
214*38e8c45fSAndroid Build Coastguard Worker // so keep trying to send the events as long as they are present in the queue.
215*38e8c45fSAndroid Build Coastguard Worker }
216*38e8c45fSAndroid Build Coastguard Worker // However, it is still up to the app to finish any events that have already been delivered
217*38e8c45fSAndroid Build Coastguard Worker // to the callbacks. If we wanted to change that behaviour and auto-finish all unfinished events
218*38e8c45fSAndroid Build Coastguard Worker // that were already sent to callbacks, we could potentially loop through "mConsumeTimes"
219*38e8c45fSAndroid Build Coastguard Worker // instead. We can't use "mBatchedSequenceNumbers" for this purpose, because it only contains
220*38e8c45fSAndroid Build Coastguard Worker // batchable (i.e., ACTION_MOVE) events that were sent to the callbacks.
221*38e8c45fSAndroid Build Coastguard Worker const size_t unfinishedEvents = mConsumeTimes.size();
222*38e8c45fSAndroid Build Coastguard Worker LOG_IF(INFO, unfinishedEvents != 0)
223*38e8c45fSAndroid Build Coastguard Worker << getName() << " has " << unfinishedEvents << " unfinished event(s)";
224*38e8c45fSAndroid Build Coastguard Worker // Remove the fd from epoll, so that Looper does not call 'handleReceiveCallback' anymore.
225*38e8c45fSAndroid Build Coastguard Worker // This must be done at the end of the destructor; otherwise, some of the other functions may
226*38e8c45fSAndroid Build Coastguard Worker // call 'setFdEvents' as a side-effect, thus adding the fd back to the epoll set of the looper.
227*38e8c45fSAndroid Build Coastguard Worker setFdEvents(0);
228*38e8c45fSAndroid Build Coastguard Worker }
229*38e8c45fSAndroid Build Coastguard Worker
handleReceiveCallback(int events)230*38e8c45fSAndroid Build Coastguard Worker int InputConsumerNoResampling::handleReceiveCallback(int events) {
231*38e8c45fSAndroid Build Coastguard Worker // Allowed return values of this function as documented in LooperCallback::handleEvent
232*38e8c45fSAndroid Build Coastguard Worker constexpr int REMOVE_CALLBACK = 0;
233*38e8c45fSAndroid Build Coastguard Worker constexpr int KEEP_CALLBACK = 1;
234*38e8c45fSAndroid Build Coastguard Worker
235*38e8c45fSAndroid Build Coastguard Worker if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
236*38e8c45fSAndroid Build Coastguard Worker // This error typically occurs when the publisher has closed the input channel
237*38e8c45fSAndroid Build Coastguard Worker // as part of removing a window or finishing an IME session, in which case
238*38e8c45fSAndroid Build Coastguard Worker // the consumer will soon be disposed as well.
239*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_TRANSPORT_CONSUMER) {
240*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "The channel was hung up or an error occurred: " << mChannel->getName();
241*38e8c45fSAndroid Build Coastguard Worker }
242*38e8c45fSAndroid Build Coastguard Worker return REMOVE_CALLBACK;
243*38e8c45fSAndroid Build Coastguard Worker }
244*38e8c45fSAndroid Build Coastguard Worker
245*38e8c45fSAndroid Build Coastguard Worker int handledEvents = 0;
246*38e8c45fSAndroid Build Coastguard Worker if (events & ALOOPER_EVENT_INPUT) {
247*38e8c45fSAndroid Build Coastguard Worker handleMessages(readAllMessages());
248*38e8c45fSAndroid Build Coastguard Worker handledEvents |= ALOOPER_EVENT_INPUT;
249*38e8c45fSAndroid Build Coastguard Worker }
250*38e8c45fSAndroid Build Coastguard Worker
251*38e8c45fSAndroid Build Coastguard Worker if (events & ALOOPER_EVENT_OUTPUT) {
252*38e8c45fSAndroid Build Coastguard Worker processOutboundEvents();
253*38e8c45fSAndroid Build Coastguard Worker handledEvents |= ALOOPER_EVENT_OUTPUT;
254*38e8c45fSAndroid Build Coastguard Worker }
255*38e8c45fSAndroid Build Coastguard Worker if (handledEvents != events) {
256*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << "Mismatch: handledEvents=" << handledEvents << ", events=" << events;
257*38e8c45fSAndroid Build Coastguard Worker }
258*38e8c45fSAndroid Build Coastguard Worker return KEEP_CALLBACK;
259*38e8c45fSAndroid Build Coastguard Worker }
260*38e8c45fSAndroid Build Coastguard Worker
processOutboundEvents()261*38e8c45fSAndroid Build Coastguard Worker void InputConsumerNoResampling::processOutboundEvents() {
262*38e8c45fSAndroid Build Coastguard Worker while (!mOutboundQueue.empty()) {
263*38e8c45fSAndroid Build Coastguard Worker const InputMessage& outboundMsg = mOutboundQueue.front();
264*38e8c45fSAndroid Build Coastguard Worker
265*38e8c45fSAndroid Build Coastguard Worker const status_t result = mChannel->sendMessage(&outboundMsg);
266*38e8c45fSAndroid Build Coastguard Worker if (result == OK) {
267*38e8c45fSAndroid Build Coastguard Worker if (outboundMsg.header.type == InputMessage::Type::FINISHED) {
268*38e8c45fSAndroid Build Coastguard Worker ATRACE_ASYNC_END("InputConsumer processing", /*cookie=*/outboundMsg.header.seq);
269*38e8c45fSAndroid Build Coastguard Worker }
270*38e8c45fSAndroid Build Coastguard Worker // Successful send. Erase the entry and keep trying to send more
271*38e8c45fSAndroid Build Coastguard Worker mOutboundQueue.pop();
272*38e8c45fSAndroid Build Coastguard Worker continue;
273*38e8c45fSAndroid Build Coastguard Worker }
274*38e8c45fSAndroid Build Coastguard Worker
275*38e8c45fSAndroid Build Coastguard Worker // Publisher is busy, try again later. Keep this entry (do not erase)
276*38e8c45fSAndroid Build Coastguard Worker if (result == WOULD_BLOCK) {
277*38e8c45fSAndroid Build Coastguard Worker setFdEvents(ALOOPER_EVENT_INPUT | ALOOPER_EVENT_OUTPUT);
278*38e8c45fSAndroid Build Coastguard Worker return; // try again later
279*38e8c45fSAndroid Build Coastguard Worker }
280*38e8c45fSAndroid Build Coastguard Worker
281*38e8c45fSAndroid Build Coastguard Worker if (result == DEAD_OBJECT) {
282*38e8c45fSAndroid Build Coastguard Worker // If there's no one to receive events in the channel, there's no point in sending them.
283*38e8c45fSAndroid Build Coastguard Worker // Drop all outbound events.
284*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "Channel " << mChannel->getName() << " died. Dropping outbound event "
285*38e8c45fSAndroid Build Coastguard Worker << outboundMsg;
286*38e8c45fSAndroid Build Coastguard Worker mOutboundQueue.pop();
287*38e8c45fSAndroid Build Coastguard Worker setFdEvents(0);
288*38e8c45fSAndroid Build Coastguard Worker continue;
289*38e8c45fSAndroid Build Coastguard Worker }
290*38e8c45fSAndroid Build Coastguard Worker // Some other error. Give up
291*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << "Failed to send outbound event on channel '" << mChannel->getName()
292*38e8c45fSAndroid Build Coastguard Worker << "'. status=" << statusToString(result) << "(" << result << ")";
293*38e8c45fSAndroid Build Coastguard Worker }
294*38e8c45fSAndroid Build Coastguard Worker
295*38e8c45fSAndroid Build Coastguard Worker // The queue is now empty. Tell looper there's no more output to expect.
296*38e8c45fSAndroid Build Coastguard Worker setFdEvents(ALOOPER_EVENT_INPUT);
297*38e8c45fSAndroid Build Coastguard Worker }
298*38e8c45fSAndroid Build Coastguard Worker
finishInputEvent(uint32_t seq,bool handled)299*38e8c45fSAndroid Build Coastguard Worker void InputConsumerNoResampling::finishInputEvent(uint32_t seq, bool handled) {
300*38e8c45fSAndroid Build Coastguard Worker ensureCalledOnLooperThread(__func__);
301*38e8c45fSAndroid Build Coastguard Worker mOutboundQueue.push(createFinishedMessage(seq, handled, popConsumeTime(seq)));
302*38e8c45fSAndroid Build Coastguard Worker // also produce finish events for all batches for this seq (if any)
303*38e8c45fSAndroid Build Coastguard Worker const auto it = mBatchedSequenceNumbers.find(seq);
304*38e8c45fSAndroid Build Coastguard Worker if (it != mBatchedSequenceNumbers.end()) {
305*38e8c45fSAndroid Build Coastguard Worker for (uint32_t subSeq : it->second) {
306*38e8c45fSAndroid Build Coastguard Worker mOutboundQueue.push(createFinishedMessage(subSeq, handled, popConsumeTime(subSeq)));
307*38e8c45fSAndroid Build Coastguard Worker }
308*38e8c45fSAndroid Build Coastguard Worker mBatchedSequenceNumbers.erase(it);
309*38e8c45fSAndroid Build Coastguard Worker }
310*38e8c45fSAndroid Build Coastguard Worker processOutboundEvents();
311*38e8c45fSAndroid Build Coastguard Worker }
312*38e8c45fSAndroid Build Coastguard Worker
probablyHasInput() const313*38e8c45fSAndroid Build Coastguard Worker bool InputConsumerNoResampling::probablyHasInput() const {
314*38e8c45fSAndroid Build Coastguard Worker // Ideally, this would only be allowed to run on the looper thread, and in production, it will.
315*38e8c45fSAndroid Build Coastguard Worker // However, for testing, it's convenient to call this while the looper thread is blocked, so
316*38e8c45fSAndroid Build Coastguard Worker // we do not call ensureCalledOnLooperThread here.
317*38e8c45fSAndroid Build Coastguard Worker return (!mBatches.empty()) || mChannel->probablyHasInput();
318*38e8c45fSAndroid Build Coastguard Worker }
319*38e8c45fSAndroid Build Coastguard Worker
reportTimeline(int32_t inputEventId,nsecs_t gpuCompletedTime,nsecs_t presentTime)320*38e8c45fSAndroid Build Coastguard Worker void InputConsumerNoResampling::reportTimeline(int32_t inputEventId, nsecs_t gpuCompletedTime,
321*38e8c45fSAndroid Build Coastguard Worker nsecs_t presentTime) {
322*38e8c45fSAndroid Build Coastguard Worker ensureCalledOnLooperThread(__func__);
323*38e8c45fSAndroid Build Coastguard Worker mOutboundQueue.push(createTimelineMessage(inputEventId, gpuCompletedTime, presentTime));
324*38e8c45fSAndroid Build Coastguard Worker processOutboundEvents();
325*38e8c45fSAndroid Build Coastguard Worker }
326*38e8c45fSAndroid Build Coastguard Worker
popConsumeTime(uint32_t seq)327*38e8c45fSAndroid Build Coastguard Worker nsecs_t InputConsumerNoResampling::popConsumeTime(uint32_t seq) {
328*38e8c45fSAndroid Build Coastguard Worker auto it = mConsumeTimes.find(seq);
329*38e8c45fSAndroid Build Coastguard Worker // Consume time will be missing if either 'finishInputEvent' is called twice, or if it was
330*38e8c45fSAndroid Build Coastguard Worker // called for the wrong (synthetic?) input event. Either way, it is a bug that should be fixed.
331*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(it == mConsumeTimes.end(), "Could not find consume time for seq=%" PRIu32,
332*38e8c45fSAndroid Build Coastguard Worker seq);
333*38e8c45fSAndroid Build Coastguard Worker nsecs_t consumeTime = it->second;
334*38e8c45fSAndroid Build Coastguard Worker mConsumeTimes.erase(it);
335*38e8c45fSAndroid Build Coastguard Worker return consumeTime;
336*38e8c45fSAndroid Build Coastguard Worker }
337*38e8c45fSAndroid Build Coastguard Worker
setFdEvents(int events)338*38e8c45fSAndroid Build Coastguard Worker void InputConsumerNoResampling::setFdEvents(int events) {
339*38e8c45fSAndroid Build Coastguard Worker if (mFdEvents != events) {
340*38e8c45fSAndroid Build Coastguard Worker mFdEvents = events;
341*38e8c45fSAndroid Build Coastguard Worker if (events != 0) {
342*38e8c45fSAndroid Build Coastguard Worker mLooper->addFd(mChannel->getFd(), 0, events, mCallback, nullptr);
343*38e8c45fSAndroid Build Coastguard Worker } else {
344*38e8c45fSAndroid Build Coastguard Worker mLooper->removeFd(mChannel->getFd());
345*38e8c45fSAndroid Build Coastguard Worker }
346*38e8c45fSAndroid Build Coastguard Worker }
347*38e8c45fSAndroid Build Coastguard Worker }
348*38e8c45fSAndroid Build Coastguard Worker
handleMessages(std::vector<InputMessage> && messages)349*38e8c45fSAndroid Build Coastguard Worker void InputConsumerNoResampling::handleMessages(std::vector<InputMessage>&& messages) {
350*38e8c45fSAndroid Build Coastguard Worker for (const InputMessage& msg : messages) {
351*38e8c45fSAndroid Build Coastguard Worker if (msg.header.type == InputMessage::Type::MOTION) {
352*38e8c45fSAndroid Build Coastguard Worker const int32_t action = msg.body.motion.action;
353*38e8c45fSAndroid Build Coastguard Worker const DeviceId deviceId = msg.body.motion.deviceId;
354*38e8c45fSAndroid Build Coastguard Worker const int32_t source = msg.body.motion.source;
355*38e8c45fSAndroid Build Coastguard Worker const bool batchableEvent = (action == AMOTION_EVENT_ACTION_MOVE ||
356*38e8c45fSAndroid Build Coastguard Worker action == AMOTION_EVENT_ACTION_HOVER_MOVE) &&
357*38e8c45fSAndroid Build Coastguard Worker (isFromSource(source, AINPUT_SOURCE_CLASS_POINTER) ||
358*38e8c45fSAndroid Build Coastguard Worker isFromSource(source, AINPUT_SOURCE_CLASS_JOYSTICK));
359*38e8c45fSAndroid Build Coastguard Worker
360*38e8c45fSAndroid Build Coastguard Worker const bool canResample = (mResamplerCreator != nullptr) &&
361*38e8c45fSAndroid Build Coastguard Worker (isFromSource(source, AINPUT_SOURCE_CLASS_POINTER));
362*38e8c45fSAndroid Build Coastguard Worker if (canResample) {
363*38e8c45fSAndroid Build Coastguard Worker if (action == AMOTION_EVENT_ACTION_DOWN) {
364*38e8c45fSAndroid Build Coastguard Worker if (std::unique_ptr<Resampler> resampler = mResamplerCreator();
365*38e8c45fSAndroid Build Coastguard Worker resampler != nullptr) {
366*38e8c45fSAndroid Build Coastguard Worker const auto [_, inserted] =
367*38e8c45fSAndroid Build Coastguard Worker mResamplers.insert(std::pair(deviceId, std::move(resampler)));
368*38e8c45fSAndroid Build Coastguard Worker LOG_IF(WARNING, !inserted) << deviceId << "already exists in mResamplers";
369*38e8c45fSAndroid Build Coastguard Worker }
370*38e8c45fSAndroid Build Coastguard Worker }
371*38e8c45fSAndroid Build Coastguard Worker }
372*38e8c45fSAndroid Build Coastguard Worker
373*38e8c45fSAndroid Build Coastguard Worker if (batchableEvent) {
374*38e8c45fSAndroid Build Coastguard Worker // add it to batch
375*38e8c45fSAndroid Build Coastguard Worker mBatches[deviceId].emplace(msg);
376*38e8c45fSAndroid Build Coastguard Worker } else {
377*38e8c45fSAndroid Build Coastguard Worker // consume all pending batches for this device immediately
378*38e8c45fSAndroid Build Coastguard Worker consumeBatchedInputEvents(deviceId, /*requestedFrameTime=*/
379*38e8c45fSAndroid Build Coastguard Worker std::numeric_limits<nsecs_t>::max());
380*38e8c45fSAndroid Build Coastguard Worker if (canResample &&
381*38e8c45fSAndroid Build Coastguard Worker (action == AMOTION_EVENT_ACTION_UP || action == AMOTION_EVENT_ACTION_CANCEL)) {
382*38e8c45fSAndroid Build Coastguard Worker LOG_IF(INFO, mResamplers.erase(deviceId) == 0)
383*38e8c45fSAndroid Build Coastguard Worker << deviceId << "does not exist in mResamplers";
384*38e8c45fSAndroid Build Coastguard Worker }
385*38e8c45fSAndroid Build Coastguard Worker handleMessage(msg);
386*38e8c45fSAndroid Build Coastguard Worker }
387*38e8c45fSAndroid Build Coastguard Worker } else {
388*38e8c45fSAndroid Build Coastguard Worker // Non-motion events shouldn't force the consumption of pending batched events
389*38e8c45fSAndroid Build Coastguard Worker handleMessage(msg);
390*38e8c45fSAndroid Build Coastguard Worker }
391*38e8c45fSAndroid Build Coastguard Worker }
392*38e8c45fSAndroid Build Coastguard Worker // At the end of this, if we still have pending batches, notify the receiver about it.
393*38e8c45fSAndroid Build Coastguard Worker
394*38e8c45fSAndroid Build Coastguard Worker // We need to carefully notify the InputConsumerCallbacks about the pending batch. The receiver
395*38e8c45fSAndroid Build Coastguard Worker // could choose to consume all events when notified about the batch. That means that the
396*38e8c45fSAndroid Build Coastguard Worker // "mBatches" variable could change when 'InputConsumerCallbacks::onBatchedInputEventPending' is
397*38e8c45fSAndroid Build Coastguard Worker // invoked. We also can't notify the InputConsumerCallbacks in a while loop until mBatches is
398*38e8c45fSAndroid Build Coastguard Worker // empty, because the receiver could choose to not consume the batch immediately.
399*38e8c45fSAndroid Build Coastguard Worker std::set<int32_t> pendingBatchSources;
400*38e8c45fSAndroid Build Coastguard Worker for (const auto& [_, pendingMessages] : mBatches) {
401*38e8c45fSAndroid Build Coastguard Worker // Assume that all messages for a given device has the same source.
402*38e8c45fSAndroid Build Coastguard Worker pendingBatchSources.insert(pendingMessages.front().body.motion.source);
403*38e8c45fSAndroid Build Coastguard Worker }
404*38e8c45fSAndroid Build Coastguard Worker for (const int32_t source : pendingBatchSources) {
405*38e8c45fSAndroid Build Coastguard Worker const bool sourceStillRemaining =
406*38e8c45fSAndroid Build Coastguard Worker std::any_of(mBatches.begin(), mBatches.end(), [=](const auto& pair) {
407*38e8c45fSAndroid Build Coastguard Worker return pair.second.front().body.motion.source == source;
408*38e8c45fSAndroid Build Coastguard Worker });
409*38e8c45fSAndroid Build Coastguard Worker if (sourceStillRemaining) {
410*38e8c45fSAndroid Build Coastguard Worker mCallbacks.onBatchedInputEventPending(source);
411*38e8c45fSAndroid Build Coastguard Worker }
412*38e8c45fSAndroid Build Coastguard Worker }
413*38e8c45fSAndroid Build Coastguard Worker }
414*38e8c45fSAndroid Build Coastguard Worker
readAllMessages()415*38e8c45fSAndroid Build Coastguard Worker std::vector<InputMessage> InputConsumerNoResampling::readAllMessages() {
416*38e8c45fSAndroid Build Coastguard Worker std::vector<InputMessage> messages;
417*38e8c45fSAndroid Build Coastguard Worker while (true) {
418*38e8c45fSAndroid Build Coastguard Worker android::base::Result<InputMessage> result = mChannel->receiveMessage();
419*38e8c45fSAndroid Build Coastguard Worker if (result.ok()) {
420*38e8c45fSAndroid Build Coastguard Worker const InputMessage& msg = *result;
421*38e8c45fSAndroid Build Coastguard Worker const auto [_, inserted] =
422*38e8c45fSAndroid Build Coastguard Worker mConsumeTimes.emplace(msg.header.seq, systemTime(SYSTEM_TIME_MONOTONIC));
423*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(!inserted, "Already have a consume time for seq=%" PRIu32,
424*38e8c45fSAndroid Build Coastguard Worker msg.header.seq);
425*38e8c45fSAndroid Build Coastguard Worker
426*38e8c45fSAndroid Build Coastguard Worker // Trace the event processing timeline - event was just read from the socket
427*38e8c45fSAndroid Build Coastguard Worker // TODO(b/329777420): distinguish between multiple instances of InputConsumer
428*38e8c45fSAndroid Build Coastguard Worker // in the same process.
429*38e8c45fSAndroid Build Coastguard Worker ATRACE_ASYNC_BEGIN("InputConsumer processing", /*cookie=*/msg.header.seq);
430*38e8c45fSAndroid Build Coastguard Worker messages.push_back(msg);
431*38e8c45fSAndroid Build Coastguard Worker } else { // !result.ok()
432*38e8c45fSAndroid Build Coastguard Worker switch (result.error().code()) {
433*38e8c45fSAndroid Build Coastguard Worker case WOULD_BLOCK: {
434*38e8c45fSAndroid Build Coastguard Worker return messages;
435*38e8c45fSAndroid Build Coastguard Worker }
436*38e8c45fSAndroid Build Coastguard Worker case DEAD_OBJECT: {
437*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << "Got a dead object for " << mChannel->getName();
438*38e8c45fSAndroid Build Coastguard Worker break;
439*38e8c45fSAndroid Build Coastguard Worker }
440*38e8c45fSAndroid Build Coastguard Worker case BAD_VALUE: {
441*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << "Got a bad value for " << mChannel->getName();
442*38e8c45fSAndroid Build Coastguard Worker break;
443*38e8c45fSAndroid Build Coastguard Worker }
444*38e8c45fSAndroid Build Coastguard Worker default: {
445*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected error: " << result.error().message();
446*38e8c45fSAndroid Build Coastguard Worker break;
447*38e8c45fSAndroid Build Coastguard Worker }
448*38e8c45fSAndroid Build Coastguard Worker }
449*38e8c45fSAndroid Build Coastguard Worker }
450*38e8c45fSAndroid Build Coastguard Worker }
451*38e8c45fSAndroid Build Coastguard Worker }
452*38e8c45fSAndroid Build Coastguard Worker
handleMessage(const InputMessage & msg) const453*38e8c45fSAndroid Build Coastguard Worker void InputConsumerNoResampling::handleMessage(const InputMessage& msg) const {
454*38e8c45fSAndroid Build Coastguard Worker switch (msg.header.type) {
455*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::KEY: {
456*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<KeyEvent> keyEvent = createKeyEvent(msg);
457*38e8c45fSAndroid Build Coastguard Worker mCallbacks.onKeyEvent(std::move(keyEvent), msg.header.seq);
458*38e8c45fSAndroid Build Coastguard Worker break;
459*38e8c45fSAndroid Build Coastguard Worker }
460*38e8c45fSAndroid Build Coastguard Worker
461*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::MOTION: {
462*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<MotionEvent> motionEvent = createMotionEvent(msg);
463*38e8c45fSAndroid Build Coastguard Worker mCallbacks.onMotionEvent(std::move(motionEvent), msg.header.seq);
464*38e8c45fSAndroid Build Coastguard Worker break;
465*38e8c45fSAndroid Build Coastguard Worker }
466*38e8c45fSAndroid Build Coastguard Worker
467*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::FINISHED:
468*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::TIMELINE: {
469*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << "Consumed a " << ftl::enum_string(msg.header.type)
470*38e8c45fSAndroid Build Coastguard Worker << " message, which should never be seen by InputConsumer on "
471*38e8c45fSAndroid Build Coastguard Worker << mChannel->getName();
472*38e8c45fSAndroid Build Coastguard Worker break;
473*38e8c45fSAndroid Build Coastguard Worker }
474*38e8c45fSAndroid Build Coastguard Worker
475*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::FOCUS: {
476*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<FocusEvent> focusEvent = createFocusEvent(msg);
477*38e8c45fSAndroid Build Coastguard Worker mCallbacks.onFocusEvent(std::move(focusEvent), msg.header.seq);
478*38e8c45fSAndroid Build Coastguard Worker break;
479*38e8c45fSAndroid Build Coastguard Worker }
480*38e8c45fSAndroid Build Coastguard Worker
481*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::CAPTURE: {
482*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<CaptureEvent> captureEvent = createCaptureEvent(msg);
483*38e8c45fSAndroid Build Coastguard Worker mCallbacks.onCaptureEvent(std::move(captureEvent), msg.header.seq);
484*38e8c45fSAndroid Build Coastguard Worker break;
485*38e8c45fSAndroid Build Coastguard Worker }
486*38e8c45fSAndroid Build Coastguard Worker
487*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::DRAG: {
488*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<DragEvent> dragEvent = createDragEvent(msg);
489*38e8c45fSAndroid Build Coastguard Worker mCallbacks.onDragEvent(std::move(dragEvent), msg.header.seq);
490*38e8c45fSAndroid Build Coastguard Worker break;
491*38e8c45fSAndroid Build Coastguard Worker }
492*38e8c45fSAndroid Build Coastguard Worker
493*38e8c45fSAndroid Build Coastguard Worker case InputMessage::Type::TOUCH_MODE: {
494*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<TouchModeEvent> touchModeEvent = createTouchModeEvent(msg);
495*38e8c45fSAndroid Build Coastguard Worker mCallbacks.onTouchModeEvent(std::move(touchModeEvent), msg.header.seq);
496*38e8c45fSAndroid Build Coastguard Worker break;
497*38e8c45fSAndroid Build Coastguard Worker }
498*38e8c45fSAndroid Build Coastguard Worker }
499*38e8c45fSAndroid Build Coastguard Worker }
500*38e8c45fSAndroid Build Coastguard Worker
501*38e8c45fSAndroid Build Coastguard Worker std::pair<std::unique_ptr<MotionEvent>, std::optional<uint32_t>>
createBatchedMotionEvent(const std::optional<nsecs_t> requestedFrameTime,std::queue<InputMessage> & messages)502*38e8c45fSAndroid Build Coastguard Worker InputConsumerNoResampling::createBatchedMotionEvent(const std::optional<nsecs_t> requestedFrameTime,
503*38e8c45fSAndroid Build Coastguard Worker std::queue<InputMessage>& messages) {
504*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<MotionEvent> motionEvent;
505*38e8c45fSAndroid Build Coastguard Worker std::optional<uint32_t> firstSeqForBatch;
506*38e8c45fSAndroid Build Coastguard Worker
507*38e8c45fSAndroid Build Coastguard Worker LOG_IF(FATAL, messages.empty()) << "messages queue is empty!";
508*38e8c45fSAndroid Build Coastguard Worker const DeviceId deviceId = messages.front().body.motion.deviceId;
509*38e8c45fSAndroid Build Coastguard Worker const auto resampler = mResamplers.find(deviceId);
510*38e8c45fSAndroid Build Coastguard Worker const nanoseconds resampleLatency = (resampler != mResamplers.cend())
511*38e8c45fSAndroid Build Coastguard Worker ? resampler->second->getResampleLatency()
512*38e8c45fSAndroid Build Coastguard Worker : nanoseconds{0};
513*38e8c45fSAndroid Build Coastguard Worker // When batching is not enabled, we want to consume all events. That's equivalent to having an
514*38e8c45fSAndroid Build Coastguard Worker // infinite requestedFrameTime.
515*38e8c45fSAndroid Build Coastguard Worker const nanoseconds adjustedFrameTime = (requestedFrameTime.has_value())
516*38e8c45fSAndroid Build Coastguard Worker ? (nanoseconds{*requestedFrameTime} - resampleLatency)
517*38e8c45fSAndroid Build Coastguard Worker : nanoseconds{std::numeric_limits<nsecs_t>::max()};
518*38e8c45fSAndroid Build Coastguard Worker
519*38e8c45fSAndroid Build Coastguard Worker while (!messages.empty() &&
520*38e8c45fSAndroid Build Coastguard Worker (messages.front().body.motion.eventTime <= adjustedFrameTime.count())) {
521*38e8c45fSAndroid Build Coastguard Worker if (motionEvent == nullptr) {
522*38e8c45fSAndroid Build Coastguard Worker motionEvent = createMotionEvent(messages.front());
523*38e8c45fSAndroid Build Coastguard Worker firstSeqForBatch = messages.front().header.seq;
524*38e8c45fSAndroid Build Coastguard Worker const auto [_, inserted] = mBatchedSequenceNumbers.insert({*firstSeqForBatch, {}});
525*38e8c45fSAndroid Build Coastguard Worker LOG_IF(FATAL, !inserted)
526*38e8c45fSAndroid Build Coastguard Worker << "The sequence " << messages.front().header.seq << " was already present!";
527*38e8c45fSAndroid Build Coastguard Worker } else {
528*38e8c45fSAndroid Build Coastguard Worker addSample(*motionEvent, messages.front());
529*38e8c45fSAndroid Build Coastguard Worker mBatchedSequenceNumbers[*firstSeqForBatch].push_back(messages.front().header.seq);
530*38e8c45fSAndroid Build Coastguard Worker }
531*38e8c45fSAndroid Build Coastguard Worker messages.pop();
532*38e8c45fSAndroid Build Coastguard Worker }
533*38e8c45fSAndroid Build Coastguard Worker
534*38e8c45fSAndroid Build Coastguard Worker // Check if resampling should be performed.
535*38e8c45fSAndroid Build Coastguard Worker InputMessage* futureSample = nullptr;
536*38e8c45fSAndroid Build Coastguard Worker if (!messages.empty()) {
537*38e8c45fSAndroid Build Coastguard Worker futureSample = &messages.front();
538*38e8c45fSAndroid Build Coastguard Worker }
539*38e8c45fSAndroid Build Coastguard Worker if ((motionEvent != nullptr) && (resampler != mResamplers.cend()) &&
540*38e8c45fSAndroid Build Coastguard Worker (requestedFrameTime.has_value())) {
541*38e8c45fSAndroid Build Coastguard Worker resampler->second->resampleMotionEvent(nanoseconds{*requestedFrameTime}, *motionEvent,
542*38e8c45fSAndroid Build Coastguard Worker futureSample);
543*38e8c45fSAndroid Build Coastguard Worker }
544*38e8c45fSAndroid Build Coastguard Worker
545*38e8c45fSAndroid Build Coastguard Worker return std::make_pair(std::move(motionEvent), firstSeqForBatch);
546*38e8c45fSAndroid Build Coastguard Worker }
547*38e8c45fSAndroid Build Coastguard Worker
consumeBatchedInputEvents(std::optional<DeviceId> deviceId,std::optional<nsecs_t> requestedFrameTime)548*38e8c45fSAndroid Build Coastguard Worker bool InputConsumerNoResampling::consumeBatchedInputEvents(
549*38e8c45fSAndroid Build Coastguard Worker std::optional<DeviceId> deviceId, std::optional<nsecs_t> requestedFrameTime) {
550*38e8c45fSAndroid Build Coastguard Worker ensureCalledOnLooperThread(__func__);
551*38e8c45fSAndroid Build Coastguard Worker bool producedEvents = false;
552*38e8c45fSAndroid Build Coastguard Worker
553*38e8c45fSAndroid Build Coastguard Worker for (auto deviceIdIter = (deviceId.has_value()) ? (mBatches.find(*deviceId))
554*38e8c45fSAndroid Build Coastguard Worker : (mBatches.begin());
555*38e8c45fSAndroid Build Coastguard Worker deviceIdIter != mBatches.cend(); ++deviceIdIter) {
556*38e8c45fSAndroid Build Coastguard Worker std::queue<InputMessage>& messages = deviceIdIter->second;
557*38e8c45fSAndroid Build Coastguard Worker auto [motion, firstSeqForBatch] = createBatchedMotionEvent(requestedFrameTime, messages);
558*38e8c45fSAndroid Build Coastguard Worker if (motion != nullptr) {
559*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(!firstSeqForBatch.has_value());
560*38e8c45fSAndroid Build Coastguard Worker mCallbacks.onMotionEvent(std::move(motion), *firstSeqForBatch);
561*38e8c45fSAndroid Build Coastguard Worker producedEvents = true;
562*38e8c45fSAndroid Build Coastguard Worker } else {
563*38e8c45fSAndroid Build Coastguard Worker // This is OK, it just means that the requestedFrameTime is too old (all events that we
564*38e8c45fSAndroid Build Coastguard Worker // have pending are in the future of the requestedFrameTime). Maybe print a warning? If
565*38e8c45fSAndroid Build Coastguard Worker // there are multiple devices active though, this might be normal and can just be
566*38e8c45fSAndroid Build Coastguard Worker // ignored, unless none of them resulted in any consumption (in that case, this function
567*38e8c45fSAndroid Build Coastguard Worker // would already return "false" so we could just leave it up to the caller).
568*38e8c45fSAndroid Build Coastguard Worker }
569*38e8c45fSAndroid Build Coastguard Worker
570*38e8c45fSAndroid Build Coastguard Worker if (deviceId.has_value()) {
571*38e8c45fSAndroid Build Coastguard Worker // We already consumed events for this device. Break here to prevent iterating over the
572*38e8c45fSAndroid Build Coastguard Worker // other devices.
573*38e8c45fSAndroid Build Coastguard Worker break;
574*38e8c45fSAndroid Build Coastguard Worker }
575*38e8c45fSAndroid Build Coastguard Worker }
576*38e8c45fSAndroid Build Coastguard Worker std::erase_if(mBatches, [](const auto& pair) { return pair.second.empty(); });
577*38e8c45fSAndroid Build Coastguard Worker return producedEvents;
578*38e8c45fSAndroid Build Coastguard Worker }
579*38e8c45fSAndroid Build Coastguard Worker
consumeBatchedInputEvents(std::optional<nsecs_t> requestedFrameTime)580*38e8c45fSAndroid Build Coastguard Worker bool InputConsumerNoResampling::consumeBatchedInputEvents(
581*38e8c45fSAndroid Build Coastguard Worker std::optional<nsecs_t> requestedFrameTime) {
582*38e8c45fSAndroid Build Coastguard Worker return consumeBatchedInputEvents(/*deviceId=*/std::nullopt, requestedFrameTime);
583*38e8c45fSAndroid Build Coastguard Worker }
584*38e8c45fSAndroid Build Coastguard Worker
ensureCalledOnLooperThread(const char * func) const585*38e8c45fSAndroid Build Coastguard Worker void InputConsumerNoResampling::ensureCalledOnLooperThread(const char* func) const {
586*38e8c45fSAndroid Build Coastguard Worker sp<Looper> callingThreadLooper = Looper::getForThread();
587*38e8c45fSAndroid Build Coastguard Worker if (callingThreadLooper != mLooper) {
588*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << "The function " << func << " can only be called on the looper thread";
589*38e8c45fSAndroid Build Coastguard Worker }
590*38e8c45fSAndroid Build Coastguard Worker }
591*38e8c45fSAndroid Build Coastguard Worker
dump() const592*38e8c45fSAndroid Build Coastguard Worker std::string InputConsumerNoResampling::dump() const {
593*38e8c45fSAndroid Build Coastguard Worker ensureCalledOnLooperThread(__func__);
594*38e8c45fSAndroid Build Coastguard Worker std::string out;
595*38e8c45fSAndroid Build Coastguard Worker if (mOutboundQueue.empty()) {
596*38e8c45fSAndroid Build Coastguard Worker out += "mOutboundQueue: <empty>\n";
597*38e8c45fSAndroid Build Coastguard Worker } else {
598*38e8c45fSAndroid Build Coastguard Worker out += "mOutboundQueue:\n";
599*38e8c45fSAndroid Build Coastguard Worker // Make a copy of mOutboundQueue for printing destructively. Unfortunately std::queue
600*38e8c45fSAndroid Build Coastguard Worker // doesn't provide a good way to iterate over the entire container.
601*38e8c45fSAndroid Build Coastguard Worker std::queue<InputMessage> tmpQueue = mOutboundQueue;
602*38e8c45fSAndroid Build Coastguard Worker while (!tmpQueue.empty()) {
603*38e8c45fSAndroid Build Coastguard Worker out += std::string(" ") + outboundMessageToString(tmpQueue.front()) + "\n";
604*38e8c45fSAndroid Build Coastguard Worker tmpQueue.pop();
605*38e8c45fSAndroid Build Coastguard Worker }
606*38e8c45fSAndroid Build Coastguard Worker }
607*38e8c45fSAndroid Build Coastguard Worker
608*38e8c45fSAndroid Build Coastguard Worker if (mBatches.empty()) {
609*38e8c45fSAndroid Build Coastguard Worker out += "mBatches: <empty>\n";
610*38e8c45fSAndroid Build Coastguard Worker } else {
611*38e8c45fSAndroid Build Coastguard Worker out += "mBatches:\n";
612*38e8c45fSAndroid Build Coastguard Worker for (const auto& [deviceId, messages] : mBatches) {
613*38e8c45fSAndroid Build Coastguard Worker out += " Device id ";
614*38e8c45fSAndroid Build Coastguard Worker out += std::to_string(deviceId);
615*38e8c45fSAndroid Build Coastguard Worker out += ":\n";
616*38e8c45fSAndroid Build Coastguard Worker // Make a copy of mOutboundQueue for printing destructively. Unfortunately std::queue
617*38e8c45fSAndroid Build Coastguard Worker // doesn't provide a good way to iterate over the entire container.
618*38e8c45fSAndroid Build Coastguard Worker std::queue<InputMessage> tmpQueue = messages;
619*38e8c45fSAndroid Build Coastguard Worker while (!tmpQueue.empty()) {
620*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(tmpQueue.front().header.type != InputMessage::Type::MOTION);
621*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<MotionEvent> motion = createMotionEvent(tmpQueue.front());
622*38e8c45fSAndroid Build Coastguard Worker out += std::string(" ") + streamableToString(*motion) + "\n";
623*38e8c45fSAndroid Build Coastguard Worker tmpQueue.pop();
624*38e8c45fSAndroid Build Coastguard Worker }
625*38e8c45fSAndroid Build Coastguard Worker }
626*38e8c45fSAndroid Build Coastguard Worker }
627*38e8c45fSAndroid Build Coastguard Worker
628*38e8c45fSAndroid Build Coastguard Worker return out;
629*38e8c45fSAndroid Build Coastguard Worker }
630*38e8c45fSAndroid Build Coastguard Worker
631*38e8c45fSAndroid Build Coastguard Worker } // namespace android
632