1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker * Copyright (C) 2010 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 "InputDispatcher"
18*38e8c45fSAndroid Build Coastguard Worker #define ATRACE_TAG ATRACE_TAG_INPUT
19*38e8c45fSAndroid Build Coastguard Worker
20*38e8c45fSAndroid Build Coastguard Worker #define LOG_NDEBUG 1
21*38e8c45fSAndroid Build Coastguard Worker
22*38e8c45fSAndroid Build Coastguard Worker #include <android-base/chrono_utils.h>
23*38e8c45fSAndroid Build Coastguard Worker #include <android-base/logging.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <android-base/properties.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <android/os/IInputConstants.h>
27*38e8c45fSAndroid Build Coastguard Worker #include <binder/Binder.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <com_android_input_flags.h>
29*38e8c45fSAndroid Build Coastguard Worker #include <ftl/enum.h>
30*38e8c45fSAndroid Build Coastguard Worker #include <log/log_event_list.h>
31*38e8c45fSAndroid Build Coastguard Worker #if defined(__ANDROID__)
32*38e8c45fSAndroid Build Coastguard Worker #include <gui/SurfaceComposerClient.h>
33*38e8c45fSAndroid Build Coastguard Worker #endif
34*38e8c45fSAndroid Build Coastguard Worker #include <input/InputDevice.h>
35*38e8c45fSAndroid Build Coastguard Worker #include <input/PrintTools.h>
36*38e8c45fSAndroid Build Coastguard Worker #include <input/TraceTools.h>
37*38e8c45fSAndroid Build Coastguard Worker #include <openssl/mem.h>
38*38e8c45fSAndroid Build Coastguard Worker #include <private/android_filesystem_config.h>
39*38e8c45fSAndroid Build Coastguard Worker #include <unistd.h>
40*38e8c45fSAndroid Build Coastguard Worker #include <utils/Trace.h>
41*38e8c45fSAndroid Build Coastguard Worker
42*38e8c45fSAndroid Build Coastguard Worker #include <cerrno>
43*38e8c45fSAndroid Build Coastguard Worker #include <cinttypes>
44*38e8c45fSAndroid Build Coastguard Worker #include <climits>
45*38e8c45fSAndroid Build Coastguard Worker #include <cstddef>
46*38e8c45fSAndroid Build Coastguard Worker #include <ctime>
47*38e8c45fSAndroid Build Coastguard Worker #include <queue>
48*38e8c45fSAndroid Build Coastguard Worker #include <sstream>
49*38e8c45fSAndroid Build Coastguard Worker
50*38e8c45fSAndroid Build Coastguard Worker #include "../InputDeviceMetricsSource.h"
51*38e8c45fSAndroid Build Coastguard Worker
52*38e8c45fSAndroid Build Coastguard Worker #include "Connection.h"
53*38e8c45fSAndroid Build Coastguard Worker #include "DebugConfig.h"
54*38e8c45fSAndroid Build Coastguard Worker #include "InputDispatcher.h"
55*38e8c45fSAndroid Build Coastguard Worker #include "InputEventTimeline.h"
56*38e8c45fSAndroid Build Coastguard Worker #include "trace/InputTracer.h"
57*38e8c45fSAndroid Build Coastguard Worker #include "trace/InputTracingPerfettoBackend.h"
58*38e8c45fSAndroid Build Coastguard Worker #include "trace/ThreadedBackend.h"
59*38e8c45fSAndroid Build Coastguard Worker
60*38e8c45fSAndroid Build Coastguard Worker #define INDENT " "
61*38e8c45fSAndroid Build Coastguard Worker #define INDENT2 " "
62*38e8c45fSAndroid Build Coastguard Worker #define INDENT3 " "
63*38e8c45fSAndroid Build Coastguard Worker #define INDENT4 " "
64*38e8c45fSAndroid Build Coastguard Worker
65*38e8c45fSAndroid Build Coastguard Worker using namespace android::ftl::flag_operators;
66*38e8c45fSAndroid Build Coastguard Worker using android::base::Error;
67*38e8c45fSAndroid Build Coastguard Worker using android::base::HwTimeoutMultiplier;
68*38e8c45fSAndroid Build Coastguard Worker using android::base::Result;
69*38e8c45fSAndroid Build Coastguard Worker using android::base::StringPrintf;
70*38e8c45fSAndroid Build Coastguard Worker using android::gui::DisplayInfo;
71*38e8c45fSAndroid Build Coastguard Worker using android::gui::FocusRequest;
72*38e8c45fSAndroid Build Coastguard Worker using android::gui::TouchOcclusionMode;
73*38e8c45fSAndroid Build Coastguard Worker using android::gui::WindowInfo;
74*38e8c45fSAndroid Build Coastguard Worker using android::gui::WindowInfoHandle;
75*38e8c45fSAndroid Build Coastguard Worker using android::os::InputEventInjectionResult;
76*38e8c45fSAndroid Build Coastguard Worker using android::os::InputEventInjectionSync;
77*38e8c45fSAndroid Build Coastguard Worker namespace input_flags = com::android::input::flags;
78*38e8c45fSAndroid Build Coastguard Worker
79*38e8c45fSAndroid Build Coastguard Worker namespace android::inputdispatcher {
80*38e8c45fSAndroid Build Coastguard Worker
81*38e8c45fSAndroid Build Coastguard Worker namespace {
82*38e8c45fSAndroid Build Coastguard Worker
83*38e8c45fSAndroid Build Coastguard Worker // Input tracing is only available on debuggable builds (userdebug and eng) when the feature
84*38e8c45fSAndroid Build Coastguard Worker // flag is enabled. When the flag is changed, tracing will only be available after reboot.
isInputTracingEnabled()85*38e8c45fSAndroid Build Coastguard Worker bool isInputTracingEnabled() {
86*38e8c45fSAndroid Build Coastguard Worker static const std::string buildType = base::GetProperty("ro.build.type", "user");
87*38e8c45fSAndroid Build Coastguard Worker static const bool isUserdebugOrEng = buildType == "userdebug" || buildType == "eng";
88*38e8c45fSAndroid Build Coastguard Worker return input_flags::enable_input_event_tracing() && isUserdebugOrEng;
89*38e8c45fSAndroid Build Coastguard Worker }
90*38e8c45fSAndroid Build Coastguard Worker
91*38e8c45fSAndroid Build Coastguard Worker // Create the input tracing backend that writes to perfetto from a single thread.
createInputTracingBackendIfEnabled()92*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<trace::InputTracingBackendInterface> createInputTracingBackendIfEnabled() {
93*38e8c45fSAndroid Build Coastguard Worker if (!isInputTracingEnabled()) {
94*38e8c45fSAndroid Build Coastguard Worker return nullptr;
95*38e8c45fSAndroid Build Coastguard Worker }
96*38e8c45fSAndroid Build Coastguard Worker return std::make_unique<trace::impl::ThreadedBackend<trace::impl::PerfettoBackend>>(
97*38e8c45fSAndroid Build Coastguard Worker trace::impl::PerfettoBackend());
98*38e8c45fSAndroid Build Coastguard Worker }
99*38e8c45fSAndroid Build Coastguard Worker
100*38e8c45fSAndroid Build Coastguard Worker template <class Entry>
ensureEventTraced(const Entry & entry)101*38e8c45fSAndroid Build Coastguard Worker void ensureEventTraced(const Entry& entry) {
102*38e8c45fSAndroid Build Coastguard Worker if (!entry.traceTracker) {
103*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << "Expected event entry to be traced, but it wasn't: " << entry;
104*38e8c45fSAndroid Build Coastguard Worker }
105*38e8c45fSAndroid Build Coastguard Worker }
106*38e8c45fSAndroid Build Coastguard Worker
107*38e8c45fSAndroid Build Coastguard Worker // Helper to get a trace tracker from a traced key or motion entry.
getTraceTracker(const EventEntry & entry)108*38e8c45fSAndroid Build Coastguard Worker const std::unique_ptr<trace::EventTrackerInterface>& getTraceTracker(const EventEntry& entry) {
109*38e8c45fSAndroid Build Coastguard Worker switch (entry.type) {
110*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::MOTION: {
111*38e8c45fSAndroid Build Coastguard Worker const auto& motion = static_cast<const MotionEntry&>(entry);
112*38e8c45fSAndroid Build Coastguard Worker ensureEventTraced(motion);
113*38e8c45fSAndroid Build Coastguard Worker return motion.traceTracker;
114*38e8c45fSAndroid Build Coastguard Worker }
115*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::KEY: {
116*38e8c45fSAndroid Build Coastguard Worker const auto& key = static_cast<const KeyEntry&>(entry);
117*38e8c45fSAndroid Build Coastguard Worker ensureEventTraced(key);
118*38e8c45fSAndroid Build Coastguard Worker return key.traceTracker;
119*38e8c45fSAndroid Build Coastguard Worker }
120*38e8c45fSAndroid Build Coastguard Worker default: {
121*38e8c45fSAndroid Build Coastguard Worker const static std::unique_ptr<trace::EventTrackerInterface> kNullTracker;
122*38e8c45fSAndroid Build Coastguard Worker return kNullTracker;
123*38e8c45fSAndroid Build Coastguard Worker }
124*38e8c45fSAndroid Build Coastguard Worker }
125*38e8c45fSAndroid Build Coastguard Worker }
126*38e8c45fSAndroid Build Coastguard Worker
127*38e8c45fSAndroid Build Coastguard Worker // Temporarily releases a held mutex for the lifetime of the instance.
128*38e8c45fSAndroid Build Coastguard Worker // Named to match std::scoped_lock
129*38e8c45fSAndroid Build Coastguard Worker class scoped_unlock {
130*38e8c45fSAndroid Build Coastguard Worker public:
scoped_unlock(std::mutex & mutex)131*38e8c45fSAndroid Build Coastguard Worker explicit scoped_unlock(std::mutex& mutex) : mMutex(mutex) { mMutex.unlock(); }
~scoped_unlock()132*38e8c45fSAndroid Build Coastguard Worker ~scoped_unlock() { mMutex.lock(); }
133*38e8c45fSAndroid Build Coastguard Worker
134*38e8c45fSAndroid Build Coastguard Worker private:
135*38e8c45fSAndroid Build Coastguard Worker std::mutex& mMutex;
136*38e8c45fSAndroid Build Coastguard Worker };
137*38e8c45fSAndroid Build Coastguard Worker
138*38e8c45fSAndroid Build Coastguard Worker // Default input dispatching timeout if there is no focused application or paused window
139*38e8c45fSAndroid Build Coastguard Worker // from which to determine an appropriate dispatching timeout.
140*38e8c45fSAndroid Build Coastguard Worker const std::chrono::duration DEFAULT_INPUT_DISPATCHING_TIMEOUT = std::chrono::milliseconds(
141*38e8c45fSAndroid Build Coastguard Worker android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
142*38e8c45fSAndroid Build Coastguard Worker HwTimeoutMultiplier());
143*38e8c45fSAndroid Build Coastguard Worker
144*38e8c45fSAndroid Build Coastguard Worker // The default minimum time gap between two user activity poke events.
145*38e8c45fSAndroid Build Coastguard Worker const std::chrono::milliseconds DEFAULT_USER_ACTIVITY_POKE_INTERVAL = 100ms;
146*38e8c45fSAndroid Build Coastguard Worker
147*38e8c45fSAndroid Build Coastguard Worker const std::chrono::duration STALE_EVENT_TIMEOUT = std::chrono::seconds(10) * HwTimeoutMultiplier();
148*38e8c45fSAndroid Build Coastguard Worker
149*38e8c45fSAndroid Build Coastguard Worker // Log a warning when an event takes longer than this to process, even if an ANR does not occur.
150*38e8c45fSAndroid Build Coastguard Worker constexpr nsecs_t SLOW_EVENT_PROCESSING_WARNING_TIMEOUT = 2000 * 1000000LL; // 2sec
151*38e8c45fSAndroid Build Coastguard Worker
152*38e8c45fSAndroid Build Coastguard Worker // Log a warning when an interception call takes longer than this to process.
153*38e8c45fSAndroid Build Coastguard Worker constexpr std::chrono::milliseconds SLOW_INTERCEPTION_THRESHOLD = 50ms;
154*38e8c45fSAndroid Build Coastguard Worker
155*38e8c45fSAndroid Build Coastguard Worker // Number of recent events to keep for debugging purposes.
156*38e8c45fSAndroid Build Coastguard Worker constexpr size_t RECENT_QUEUE_MAX_SIZE = 10;
157*38e8c45fSAndroid Build Coastguard Worker
158*38e8c45fSAndroid Build Coastguard Worker // Interval at which we should push the atom gathering input event latencies in
159*38e8c45fSAndroid Build Coastguard Worker // LatencyAggregatorWithHistograms
160*38e8c45fSAndroid Build Coastguard Worker constexpr nsecs_t LATENCY_STATISTICS_PUSH_INTERVAL = 6 * 3600 * 1000000000LL; // 6 hours
161*38e8c45fSAndroid Build Coastguard Worker
162*38e8c45fSAndroid Build Coastguard Worker // Event log tags. See EventLogTags.logtags for reference.
163*38e8c45fSAndroid Build Coastguard Worker constexpr int LOGTAG_INPUT_INTERACTION = 62000;
164*38e8c45fSAndroid Build Coastguard Worker constexpr int LOGTAG_INPUT_FOCUS = 62001;
165*38e8c45fSAndroid Build Coastguard Worker constexpr int LOGTAG_INPUT_CANCEL = 62003;
166*38e8c45fSAndroid Build Coastguard Worker
167*38e8c45fSAndroid Build Coastguard Worker const ui::Transform kIdentityTransform;
168*38e8c45fSAndroid Build Coastguard Worker
now()169*38e8c45fSAndroid Build Coastguard Worker inline nsecs_t now() {
170*38e8c45fSAndroid Build Coastguard Worker return systemTime(SYSTEM_TIME_MONOTONIC);
171*38e8c45fSAndroid Build Coastguard Worker }
172*38e8c45fSAndroid Build Coastguard Worker
binderToString(const sp<IBinder> & binder)173*38e8c45fSAndroid Build Coastguard Worker inline const std::string binderToString(const sp<IBinder>& binder) {
174*38e8c45fSAndroid Build Coastguard Worker if (binder == nullptr) {
175*38e8c45fSAndroid Build Coastguard Worker return "<null>";
176*38e8c45fSAndroid Build Coastguard Worker }
177*38e8c45fSAndroid Build Coastguard Worker return StringPrintf("%p", binder.get());
178*38e8c45fSAndroid Build Coastguard Worker }
179*38e8c45fSAndroid Build Coastguard Worker
uidString(const gui::Uid & uid)180*38e8c45fSAndroid Build Coastguard Worker static std::string uidString(const gui::Uid& uid) {
181*38e8c45fSAndroid Build Coastguard Worker return uid.toString();
182*38e8c45fSAndroid Build Coastguard Worker }
183*38e8c45fSAndroid Build Coastguard Worker
checkKeyAction(int32_t action)184*38e8c45fSAndroid Build Coastguard Worker Result<void> checkKeyAction(int32_t action) {
185*38e8c45fSAndroid Build Coastguard Worker switch (action) {
186*38e8c45fSAndroid Build Coastguard Worker case AKEY_EVENT_ACTION_DOWN:
187*38e8c45fSAndroid Build Coastguard Worker case AKEY_EVENT_ACTION_UP:
188*38e8c45fSAndroid Build Coastguard Worker return {};
189*38e8c45fSAndroid Build Coastguard Worker default:
190*38e8c45fSAndroid Build Coastguard Worker return Error() << "Key event has invalid action code " << action;
191*38e8c45fSAndroid Build Coastguard Worker }
192*38e8c45fSAndroid Build Coastguard Worker }
193*38e8c45fSAndroid Build Coastguard Worker
validateKeyEvent(int32_t action)194*38e8c45fSAndroid Build Coastguard Worker Result<void> validateKeyEvent(int32_t action) {
195*38e8c45fSAndroid Build Coastguard Worker return checkKeyAction(action);
196*38e8c45fSAndroid Build Coastguard Worker }
197*38e8c45fSAndroid Build Coastguard Worker
checkMotionAction(int32_t action,int32_t actionButton,int32_t pointerCount)198*38e8c45fSAndroid Build Coastguard Worker Result<void> checkMotionAction(int32_t action, int32_t actionButton, int32_t pointerCount) {
199*38e8c45fSAndroid Build Coastguard Worker switch (MotionEvent::getActionMasked(action)) {
200*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_DOWN:
201*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_UP: {
202*38e8c45fSAndroid Build Coastguard Worker if (pointerCount != 1) {
203*38e8c45fSAndroid Build Coastguard Worker return Error() << "invalid pointer count " << pointerCount;
204*38e8c45fSAndroid Build Coastguard Worker }
205*38e8c45fSAndroid Build Coastguard Worker return {};
206*38e8c45fSAndroid Build Coastguard Worker }
207*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_MOVE:
208*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_HOVER_ENTER:
209*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_HOVER_MOVE:
210*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_HOVER_EXIT: {
211*38e8c45fSAndroid Build Coastguard Worker if (pointerCount < 1) {
212*38e8c45fSAndroid Build Coastguard Worker return Error() << "invalid pointer count " << pointerCount;
213*38e8c45fSAndroid Build Coastguard Worker }
214*38e8c45fSAndroid Build Coastguard Worker return {};
215*38e8c45fSAndroid Build Coastguard Worker }
216*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_CANCEL:
217*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_OUTSIDE:
218*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_SCROLL:
219*38e8c45fSAndroid Build Coastguard Worker return {};
220*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_POINTER_DOWN:
221*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_POINTER_UP: {
222*38e8c45fSAndroid Build Coastguard Worker const int32_t index = MotionEvent::getActionIndex(action);
223*38e8c45fSAndroid Build Coastguard Worker if (index < 0) {
224*38e8c45fSAndroid Build Coastguard Worker return Error() << "invalid index " << index << " for "
225*38e8c45fSAndroid Build Coastguard Worker << MotionEvent::actionToString(action);
226*38e8c45fSAndroid Build Coastguard Worker }
227*38e8c45fSAndroid Build Coastguard Worker if (index >= pointerCount) {
228*38e8c45fSAndroid Build Coastguard Worker return Error() << "invalid index " << index << " for pointerCount " << pointerCount;
229*38e8c45fSAndroid Build Coastguard Worker }
230*38e8c45fSAndroid Build Coastguard Worker if (pointerCount <= 1) {
231*38e8c45fSAndroid Build Coastguard Worker return Error() << "invalid pointer count " << pointerCount << " for "
232*38e8c45fSAndroid Build Coastguard Worker << MotionEvent::actionToString(action);
233*38e8c45fSAndroid Build Coastguard Worker }
234*38e8c45fSAndroid Build Coastguard Worker return {};
235*38e8c45fSAndroid Build Coastguard Worker }
236*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_BUTTON_PRESS:
237*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_BUTTON_RELEASE: {
238*38e8c45fSAndroid Build Coastguard Worker if (actionButton == 0) {
239*38e8c45fSAndroid Build Coastguard Worker return Error() << "action button should be nonzero for "
240*38e8c45fSAndroid Build Coastguard Worker << MotionEvent::actionToString(action);
241*38e8c45fSAndroid Build Coastguard Worker }
242*38e8c45fSAndroid Build Coastguard Worker return {};
243*38e8c45fSAndroid Build Coastguard Worker }
244*38e8c45fSAndroid Build Coastguard Worker default:
245*38e8c45fSAndroid Build Coastguard Worker return Error() << "invalid action " << action;
246*38e8c45fSAndroid Build Coastguard Worker }
247*38e8c45fSAndroid Build Coastguard Worker }
248*38e8c45fSAndroid Build Coastguard Worker
millis(std::chrono::nanoseconds t)249*38e8c45fSAndroid Build Coastguard Worker int64_t millis(std::chrono::nanoseconds t) {
250*38e8c45fSAndroid Build Coastguard Worker return std::chrono::duration_cast<std::chrono::milliseconds>(t).count();
251*38e8c45fSAndroid Build Coastguard Worker }
252*38e8c45fSAndroid Build Coastguard Worker
validateMotionEvent(int32_t action,int32_t actionButton,size_t pointerCount,const PointerProperties * pointerProperties)253*38e8c45fSAndroid Build Coastguard Worker Result<void> validateMotionEvent(int32_t action, int32_t actionButton, size_t pointerCount,
254*38e8c45fSAndroid Build Coastguard Worker const PointerProperties* pointerProperties) {
255*38e8c45fSAndroid Build Coastguard Worker Result<void> actionCheck = checkMotionAction(action, actionButton, pointerCount);
256*38e8c45fSAndroid Build Coastguard Worker if (!actionCheck.ok()) {
257*38e8c45fSAndroid Build Coastguard Worker return actionCheck;
258*38e8c45fSAndroid Build Coastguard Worker }
259*38e8c45fSAndroid Build Coastguard Worker if (pointerCount < 1 || pointerCount > MAX_POINTERS) {
260*38e8c45fSAndroid Build Coastguard Worker return Error() << "Motion event has invalid pointer count " << pointerCount
261*38e8c45fSAndroid Build Coastguard Worker << "; value must be between 1 and " << MAX_POINTERS << ".";
262*38e8c45fSAndroid Build Coastguard Worker }
263*38e8c45fSAndroid Build Coastguard Worker std::bitset<MAX_POINTER_ID + 1> pointerIdBits;
264*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < pointerCount; i++) {
265*38e8c45fSAndroid Build Coastguard Worker int32_t id = pointerProperties[i].id;
266*38e8c45fSAndroid Build Coastguard Worker if (id < 0 || id > MAX_POINTER_ID) {
267*38e8c45fSAndroid Build Coastguard Worker return Error() << "Motion event has invalid pointer id " << id
268*38e8c45fSAndroid Build Coastguard Worker << "; value must be between 0 and " << MAX_POINTER_ID;
269*38e8c45fSAndroid Build Coastguard Worker }
270*38e8c45fSAndroid Build Coastguard Worker if (pointerIdBits.test(id)) {
271*38e8c45fSAndroid Build Coastguard Worker return Error() << "Motion event has duplicate pointer id " << id;
272*38e8c45fSAndroid Build Coastguard Worker }
273*38e8c45fSAndroid Build Coastguard Worker pointerIdBits.set(id);
274*38e8c45fSAndroid Build Coastguard Worker }
275*38e8c45fSAndroid Build Coastguard Worker return {};
276*38e8c45fSAndroid Build Coastguard Worker }
277*38e8c45fSAndroid Build Coastguard Worker
validateInputEvent(const InputEvent & event)278*38e8c45fSAndroid Build Coastguard Worker Result<void> validateInputEvent(const InputEvent& event) {
279*38e8c45fSAndroid Build Coastguard Worker switch (event.getType()) {
280*38e8c45fSAndroid Build Coastguard Worker case InputEventType::KEY: {
281*38e8c45fSAndroid Build Coastguard Worker const KeyEvent& key = static_cast<const KeyEvent&>(event);
282*38e8c45fSAndroid Build Coastguard Worker const int32_t action = key.getAction();
283*38e8c45fSAndroid Build Coastguard Worker return validateKeyEvent(action);
284*38e8c45fSAndroid Build Coastguard Worker }
285*38e8c45fSAndroid Build Coastguard Worker case InputEventType::MOTION: {
286*38e8c45fSAndroid Build Coastguard Worker const MotionEvent& motion = static_cast<const MotionEvent&>(event);
287*38e8c45fSAndroid Build Coastguard Worker const int32_t action = motion.getAction();
288*38e8c45fSAndroid Build Coastguard Worker const size_t pointerCount = motion.getPointerCount();
289*38e8c45fSAndroid Build Coastguard Worker const PointerProperties* pointerProperties = motion.getPointerProperties();
290*38e8c45fSAndroid Build Coastguard Worker const int32_t actionButton = motion.getActionButton();
291*38e8c45fSAndroid Build Coastguard Worker return validateMotionEvent(action, actionButton, pointerCount, pointerProperties);
292*38e8c45fSAndroid Build Coastguard Worker }
293*38e8c45fSAndroid Build Coastguard Worker default: {
294*38e8c45fSAndroid Build Coastguard Worker return {};
295*38e8c45fSAndroid Build Coastguard Worker }
296*38e8c45fSAndroid Build Coastguard Worker }
297*38e8c45fSAndroid Build Coastguard Worker }
298*38e8c45fSAndroid Build Coastguard Worker
getPointerIds(const std::vector<PointerProperties> & pointers)299*38e8c45fSAndroid Build Coastguard Worker std::bitset<MAX_POINTER_ID + 1> getPointerIds(const std::vector<PointerProperties>& pointers) {
300*38e8c45fSAndroid Build Coastguard Worker std::bitset<MAX_POINTER_ID + 1> pointerIds;
301*38e8c45fSAndroid Build Coastguard Worker for (const PointerProperties& pointer : pointers) {
302*38e8c45fSAndroid Build Coastguard Worker pointerIds.set(pointer.id);
303*38e8c45fSAndroid Build Coastguard Worker }
304*38e8c45fSAndroid Build Coastguard Worker return pointerIds;
305*38e8c45fSAndroid Build Coastguard Worker }
306*38e8c45fSAndroid Build Coastguard Worker
dumpRegion(const Region & region)307*38e8c45fSAndroid Build Coastguard Worker std::string dumpRegion(const Region& region) {
308*38e8c45fSAndroid Build Coastguard Worker if (region.isEmpty()) {
309*38e8c45fSAndroid Build Coastguard Worker return "<empty>";
310*38e8c45fSAndroid Build Coastguard Worker }
311*38e8c45fSAndroid Build Coastguard Worker
312*38e8c45fSAndroid Build Coastguard Worker std::string dump;
313*38e8c45fSAndroid Build Coastguard Worker bool first = true;
314*38e8c45fSAndroid Build Coastguard Worker Region::const_iterator cur = region.begin();
315*38e8c45fSAndroid Build Coastguard Worker Region::const_iterator const tail = region.end();
316*38e8c45fSAndroid Build Coastguard Worker while (cur != tail) {
317*38e8c45fSAndroid Build Coastguard Worker if (first) {
318*38e8c45fSAndroid Build Coastguard Worker first = false;
319*38e8c45fSAndroid Build Coastguard Worker } else {
320*38e8c45fSAndroid Build Coastguard Worker dump += "|";
321*38e8c45fSAndroid Build Coastguard Worker }
322*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf("[%d,%d][%d,%d]", cur->left, cur->top, cur->right, cur->bottom);
323*38e8c45fSAndroid Build Coastguard Worker cur++;
324*38e8c45fSAndroid Build Coastguard Worker }
325*38e8c45fSAndroid Build Coastguard Worker return dump;
326*38e8c45fSAndroid Build Coastguard Worker }
327*38e8c45fSAndroid Build Coastguard Worker
dumpQueue(const std::deque<std::unique_ptr<DispatchEntry>> & queue,nsecs_t currentTime)328*38e8c45fSAndroid Build Coastguard Worker std::string dumpQueue(const std::deque<std::unique_ptr<DispatchEntry>>& queue,
329*38e8c45fSAndroid Build Coastguard Worker nsecs_t currentTime) {
330*38e8c45fSAndroid Build Coastguard Worker constexpr size_t maxEntries = 50; // max events to print
331*38e8c45fSAndroid Build Coastguard Worker constexpr size_t skipBegin = maxEntries / 2;
332*38e8c45fSAndroid Build Coastguard Worker const size_t skipEnd = queue.size() - maxEntries / 2;
333*38e8c45fSAndroid Build Coastguard Worker // skip from maxEntries / 2 ... size() - maxEntries/2
334*38e8c45fSAndroid Build Coastguard Worker // only print from 0 .. skipBegin and then from skipEnd .. size()
335*38e8c45fSAndroid Build Coastguard Worker
336*38e8c45fSAndroid Build Coastguard Worker std::string dump;
337*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < queue.size(); i++) {
338*38e8c45fSAndroid Build Coastguard Worker const DispatchEntry& entry = *queue[i];
339*38e8c45fSAndroid Build Coastguard Worker if (i >= skipBegin && i < skipEnd) {
340*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT4 "<skipped %zu entries>\n", skipEnd - skipBegin);
341*38e8c45fSAndroid Build Coastguard Worker i = skipEnd - 1; // it will be incremented to "skipEnd" by 'continue'
342*38e8c45fSAndroid Build Coastguard Worker continue;
343*38e8c45fSAndroid Build Coastguard Worker }
344*38e8c45fSAndroid Build Coastguard Worker dump.append(INDENT4);
345*38e8c45fSAndroid Build Coastguard Worker dump += entry.eventEntry->getDescription();
346*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(", seq=%" PRIu32 ", targetFlags=%s, age=%" PRId64 "ms", entry.seq,
347*38e8c45fSAndroid Build Coastguard Worker entry.targetFlags.string().c_str(),
348*38e8c45fSAndroid Build Coastguard Worker ns2ms(currentTime - entry.eventEntry->eventTime));
349*38e8c45fSAndroid Build Coastguard Worker if (entry.deliveryTime != 0) {
350*38e8c45fSAndroid Build Coastguard Worker // This entry was delivered, so add information on how long we've been waiting
351*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(", wait=%" PRId64 "ms", ns2ms(currentTime - entry.deliveryTime));
352*38e8c45fSAndroid Build Coastguard Worker }
353*38e8c45fSAndroid Build Coastguard Worker dump.append("\n");
354*38e8c45fSAndroid Build Coastguard Worker }
355*38e8c45fSAndroid Build Coastguard Worker return dump;
356*38e8c45fSAndroid Build Coastguard Worker }
357*38e8c45fSAndroid Build Coastguard Worker
358*38e8c45fSAndroid Build Coastguard Worker /**
359*38e8c45fSAndroid Build Coastguard Worker * Find the entry in std::unordered_map by key, and return it.
360*38e8c45fSAndroid Build Coastguard Worker * If the entry is not found, return a default constructed entry.
361*38e8c45fSAndroid Build Coastguard Worker *
362*38e8c45fSAndroid Build Coastguard Worker * Useful when the entries are vectors, since an empty vector will be returned
363*38e8c45fSAndroid Build Coastguard Worker * if the entry is not found.
364*38e8c45fSAndroid Build Coastguard Worker * Also useful when the entries are sp<>. If an entry is not found, nullptr is returned.
365*38e8c45fSAndroid Build Coastguard Worker */
366*38e8c45fSAndroid Build Coastguard Worker template <typename K, typename V>
getValueByKey(const std::unordered_map<K,V> & map,K key)367*38e8c45fSAndroid Build Coastguard Worker V getValueByKey(const std::unordered_map<K, V>& map, K key) {
368*38e8c45fSAndroid Build Coastguard Worker auto it = map.find(key);
369*38e8c45fSAndroid Build Coastguard Worker return it != map.end() ? it->second : V{};
370*38e8c45fSAndroid Build Coastguard Worker }
371*38e8c45fSAndroid Build Coastguard Worker
haveSameToken(const sp<WindowInfoHandle> & first,const sp<WindowInfoHandle> & second)372*38e8c45fSAndroid Build Coastguard Worker bool haveSameToken(const sp<WindowInfoHandle>& first, const sp<WindowInfoHandle>& second) {
373*38e8c45fSAndroid Build Coastguard Worker if (first == second) {
374*38e8c45fSAndroid Build Coastguard Worker return true;
375*38e8c45fSAndroid Build Coastguard Worker }
376*38e8c45fSAndroid Build Coastguard Worker
377*38e8c45fSAndroid Build Coastguard Worker if (first == nullptr || second == nullptr) {
378*38e8c45fSAndroid Build Coastguard Worker return false;
379*38e8c45fSAndroid Build Coastguard Worker }
380*38e8c45fSAndroid Build Coastguard Worker
381*38e8c45fSAndroid Build Coastguard Worker return first->getToken() == second->getToken();
382*38e8c45fSAndroid Build Coastguard Worker }
383*38e8c45fSAndroid Build Coastguard Worker
haveSameApplicationToken(const WindowInfo * first,const WindowInfo * second)384*38e8c45fSAndroid Build Coastguard Worker bool haveSameApplicationToken(const WindowInfo* first, const WindowInfo* second) {
385*38e8c45fSAndroid Build Coastguard Worker if (first == nullptr || second == nullptr) {
386*38e8c45fSAndroid Build Coastguard Worker return false;
387*38e8c45fSAndroid Build Coastguard Worker }
388*38e8c45fSAndroid Build Coastguard Worker return first->applicationInfo.token != nullptr &&
389*38e8c45fSAndroid Build Coastguard Worker first->applicationInfo.token == second->applicationInfo.token;
390*38e8c45fSAndroid Build Coastguard Worker }
391*38e8c45fSAndroid Build Coastguard Worker
392*38e8c45fSAndroid Build Coastguard Worker template <typename T>
firstMarkedBit(T set)393*38e8c45fSAndroid Build Coastguard Worker size_t firstMarkedBit(T set) {
394*38e8c45fSAndroid Build Coastguard Worker // TODO: replace with std::countr_zero from <bit> when that's available
395*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(set.none());
396*38e8c45fSAndroid Build Coastguard Worker size_t i = 0;
397*38e8c45fSAndroid Build Coastguard Worker while (!set.test(i)) {
398*38e8c45fSAndroid Build Coastguard Worker i++;
399*38e8c45fSAndroid Build Coastguard Worker }
400*38e8c45fSAndroid Build Coastguard Worker return i;
401*38e8c45fSAndroid Build Coastguard Worker }
402*38e8c45fSAndroid Build Coastguard Worker
createDispatchEntry(const IdGenerator & idGenerator,const InputTarget & inputTarget,std::shared_ptr<const EventEntry> eventEntry,ftl::Flags<InputTarget::Flags> inputTargetFlags,int64_t vsyncId,trace::InputTracerInterface * tracer)403*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<DispatchEntry> createDispatchEntry(const IdGenerator& idGenerator,
404*38e8c45fSAndroid Build Coastguard Worker const InputTarget& inputTarget,
405*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const EventEntry> eventEntry,
406*38e8c45fSAndroid Build Coastguard Worker ftl::Flags<InputTarget::Flags> inputTargetFlags,
407*38e8c45fSAndroid Build Coastguard Worker int64_t vsyncId,
408*38e8c45fSAndroid Build Coastguard Worker trace::InputTracerInterface* tracer) {
409*38e8c45fSAndroid Build Coastguard Worker const bool zeroCoords = inputTargetFlags.test(InputTarget::Flags::ZERO_COORDS);
410*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle> win = inputTarget.windowHandle;
411*38e8c45fSAndroid Build Coastguard Worker const std::optional<int32_t> windowId =
412*38e8c45fSAndroid Build Coastguard Worker win ? std::make_optional(win->getInfo()->id) : std::nullopt;
413*38e8c45fSAndroid Build Coastguard Worker // Assume the only targets that are not associated with a window are global monitors, and use
414*38e8c45fSAndroid Build Coastguard Worker // the system UID for global monitors for tracing purposes.
415*38e8c45fSAndroid Build Coastguard Worker const gui::Uid uid = win ? win->getInfo()->ownerUid : gui::Uid(AID_SYSTEM);
416*38e8c45fSAndroid Build Coastguard Worker
417*38e8c45fSAndroid Build Coastguard Worker if (inputTarget.useDefaultPointerTransform() && !zeroCoords) {
418*38e8c45fSAndroid Build Coastguard Worker const ui::Transform& transform = inputTarget.getDefaultPointerTransform();
419*38e8c45fSAndroid Build Coastguard Worker return std::make_unique<DispatchEntry>(eventEntry, inputTargetFlags, transform,
420*38e8c45fSAndroid Build Coastguard Worker inputTarget.displayTransform,
421*38e8c45fSAndroid Build Coastguard Worker inputTarget.globalScaleFactor, uid, vsyncId,
422*38e8c45fSAndroid Build Coastguard Worker windowId);
423*38e8c45fSAndroid Build Coastguard Worker }
424*38e8c45fSAndroid Build Coastguard Worker
425*38e8c45fSAndroid Build Coastguard Worker ALOG_ASSERT(eventEntry->type == EventEntry::Type::MOTION);
426*38e8c45fSAndroid Build Coastguard Worker const MotionEntry& motionEntry = static_cast<const MotionEntry&>(*eventEntry);
427*38e8c45fSAndroid Build Coastguard Worker
428*38e8c45fSAndroid Build Coastguard Worker std::vector<PointerCoords> pointerCoords{motionEntry.getPointerCount()};
429*38e8c45fSAndroid Build Coastguard Worker
430*38e8c45fSAndroid Build Coastguard Worker const ui::Transform* transform = &kIdentityTransform;
431*38e8c45fSAndroid Build Coastguard Worker const ui::Transform* displayTransform = &kIdentityTransform;
432*38e8c45fSAndroid Build Coastguard Worker if (zeroCoords) {
433*38e8c45fSAndroid Build Coastguard Worker std::for_each(pointerCoords.begin(), pointerCoords.end(), [](auto& pc) { pc.clear(); });
434*38e8c45fSAndroid Build Coastguard Worker } else {
435*38e8c45fSAndroid Build Coastguard Worker // Use the first pointer information to normalize all other pointers. This could be any
436*38e8c45fSAndroid Build Coastguard Worker // pointer as long as all other pointers are normalized to the same value and the final
437*38e8c45fSAndroid Build Coastguard Worker // DispatchEntry uses the transform for the normalized pointer.
438*38e8c45fSAndroid Build Coastguard Worker transform =
439*38e8c45fSAndroid Build Coastguard Worker &inputTarget.getTransformForPointer(firstMarkedBit(inputTarget.getPointerIds()));
440*38e8c45fSAndroid Build Coastguard Worker const ui::Transform inverseTransform = transform->inverse();
441*38e8c45fSAndroid Build Coastguard Worker displayTransform = &inputTarget.displayTransform;
442*38e8c45fSAndroid Build Coastguard Worker
443*38e8c45fSAndroid Build Coastguard Worker // Iterate through all pointers in the event to normalize against the first.
444*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < motionEntry.getPointerCount(); i++) {
445*38e8c45fSAndroid Build Coastguard Worker PointerCoords& newCoords = pointerCoords[i];
446*38e8c45fSAndroid Build Coastguard Worker const auto pointerId = motionEntry.pointerProperties[i].id;
447*38e8c45fSAndroid Build Coastguard Worker const ui::Transform& currTransform = inputTarget.getTransformForPointer(pointerId);
448*38e8c45fSAndroid Build Coastguard Worker
449*38e8c45fSAndroid Build Coastguard Worker newCoords.copyFrom(motionEntry.pointerCoords[i]);
450*38e8c45fSAndroid Build Coastguard Worker // First, apply the current pointer's transform to update the coordinates into
451*38e8c45fSAndroid Build Coastguard Worker // window space.
452*38e8c45fSAndroid Build Coastguard Worker MotionEvent::calculateTransformedCoordsInPlace(newCoords, motionEntry.source,
453*38e8c45fSAndroid Build Coastguard Worker motionEntry.flags, currTransform);
454*38e8c45fSAndroid Build Coastguard Worker // Next, apply the inverse transform of the normalized coordinates so the
455*38e8c45fSAndroid Build Coastguard Worker // current coordinates are transformed into the normalized coordinate space.
456*38e8c45fSAndroid Build Coastguard Worker MotionEvent::calculateTransformedCoordsInPlace(newCoords, motionEntry.source,
457*38e8c45fSAndroid Build Coastguard Worker motionEntry.flags, inverseTransform);
458*38e8c45fSAndroid Build Coastguard Worker }
459*38e8c45fSAndroid Build Coastguard Worker }
460*38e8c45fSAndroid Build Coastguard Worker
461*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<MotionEntry> combinedMotionEntry =
462*38e8c45fSAndroid Build Coastguard Worker std::make_unique<MotionEntry>(idGenerator.nextId(), motionEntry.injectionState,
463*38e8c45fSAndroid Build Coastguard Worker motionEntry.eventTime, motionEntry.deviceId,
464*38e8c45fSAndroid Build Coastguard Worker motionEntry.source, motionEntry.displayId,
465*38e8c45fSAndroid Build Coastguard Worker motionEntry.policyFlags, motionEntry.action,
466*38e8c45fSAndroid Build Coastguard Worker motionEntry.actionButton, motionEntry.flags,
467*38e8c45fSAndroid Build Coastguard Worker motionEntry.metaState, motionEntry.buttonState,
468*38e8c45fSAndroid Build Coastguard Worker motionEntry.classification, motionEntry.edgeFlags,
469*38e8c45fSAndroid Build Coastguard Worker motionEntry.xPrecision, motionEntry.yPrecision,
470*38e8c45fSAndroid Build Coastguard Worker motionEntry.xCursorPosition, motionEntry.yCursorPosition,
471*38e8c45fSAndroid Build Coastguard Worker motionEntry.downTime, motionEntry.pointerProperties,
472*38e8c45fSAndroid Build Coastguard Worker pointerCoords);
473*38e8c45fSAndroid Build Coastguard Worker if (tracer) {
474*38e8c45fSAndroid Build Coastguard Worker combinedMotionEntry->traceTracker =
475*38e8c45fSAndroid Build Coastguard Worker tracer->traceDerivedEvent(*combinedMotionEntry, *motionEntry.traceTracker);
476*38e8c45fSAndroid Build Coastguard Worker }
477*38e8c45fSAndroid Build Coastguard Worker
478*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<DispatchEntry> dispatchEntry =
479*38e8c45fSAndroid Build Coastguard Worker std::make_unique<DispatchEntry>(std::move(combinedMotionEntry), inputTargetFlags,
480*38e8c45fSAndroid Build Coastguard Worker *transform, *displayTransform,
481*38e8c45fSAndroid Build Coastguard Worker inputTarget.globalScaleFactor, uid, vsyncId, windowId);
482*38e8c45fSAndroid Build Coastguard Worker return dispatchEntry;
483*38e8c45fSAndroid Build Coastguard Worker }
484*38e8c45fSAndroid Build Coastguard Worker
485*38e8c45fSAndroid Build Coastguard Worker template <typename T>
sharedPointersEqual(const std::shared_ptr<T> & lhs,const std::shared_ptr<T> & rhs)486*38e8c45fSAndroid Build Coastguard Worker bool sharedPointersEqual(const std::shared_ptr<T>& lhs, const std::shared_ptr<T>& rhs) {
487*38e8c45fSAndroid Build Coastguard Worker if (lhs == nullptr && rhs == nullptr) {
488*38e8c45fSAndroid Build Coastguard Worker return true;
489*38e8c45fSAndroid Build Coastguard Worker }
490*38e8c45fSAndroid Build Coastguard Worker if (lhs == nullptr || rhs == nullptr) {
491*38e8c45fSAndroid Build Coastguard Worker return false;
492*38e8c45fSAndroid Build Coastguard Worker }
493*38e8c45fSAndroid Build Coastguard Worker return *lhs == *rhs;
494*38e8c45fSAndroid Build Coastguard Worker }
495*38e8c45fSAndroid Build Coastguard Worker
createKeyEvent(const KeyEntry & entry)496*38e8c45fSAndroid Build Coastguard Worker KeyEvent createKeyEvent(const KeyEntry& entry) {
497*38e8c45fSAndroid Build Coastguard Worker KeyEvent event;
498*38e8c45fSAndroid Build Coastguard Worker event.initialize(entry.id, entry.deviceId, entry.source, entry.displayId, INVALID_HMAC,
499*38e8c45fSAndroid Build Coastguard Worker entry.action, entry.flags, entry.keyCode, entry.scanCode, entry.metaState,
500*38e8c45fSAndroid Build Coastguard Worker entry.repeatCount, entry.downTime, entry.eventTime);
501*38e8c45fSAndroid Build Coastguard Worker return event;
502*38e8c45fSAndroid Build Coastguard Worker }
503*38e8c45fSAndroid Build Coastguard Worker
shouldReportMetricsForConnection(const Connection & connection)504*38e8c45fSAndroid Build Coastguard Worker bool shouldReportMetricsForConnection(const Connection& connection) {
505*38e8c45fSAndroid Build Coastguard Worker // Do not keep track of gesture monitors. They receive every event and would disproportionately
506*38e8c45fSAndroid Build Coastguard Worker // affect the statistics.
507*38e8c45fSAndroid Build Coastguard Worker if (connection.monitor) {
508*38e8c45fSAndroid Build Coastguard Worker return false;
509*38e8c45fSAndroid Build Coastguard Worker }
510*38e8c45fSAndroid Build Coastguard Worker // If the connection is experiencing ANR, let's skip it. We have separate ANR metrics
511*38e8c45fSAndroid Build Coastguard Worker if (!connection.responsive) {
512*38e8c45fSAndroid Build Coastguard Worker return false;
513*38e8c45fSAndroid Build Coastguard Worker }
514*38e8c45fSAndroid Build Coastguard Worker return true;
515*38e8c45fSAndroid Build Coastguard Worker }
516*38e8c45fSAndroid Build Coastguard Worker
shouldReportFinishedEvent(const DispatchEntry & dispatchEntry,const Connection & connection)517*38e8c45fSAndroid Build Coastguard Worker bool shouldReportFinishedEvent(const DispatchEntry& dispatchEntry, const Connection& connection) {
518*38e8c45fSAndroid Build Coastguard Worker const EventEntry& eventEntry = *dispatchEntry.eventEntry;
519*38e8c45fSAndroid Build Coastguard Worker const int32_t& inputEventId = eventEntry.id;
520*38e8c45fSAndroid Build Coastguard Worker if (inputEventId == android::os::IInputConstants::INVALID_INPUT_EVENT_ID) {
521*38e8c45fSAndroid Build Coastguard Worker return false;
522*38e8c45fSAndroid Build Coastguard Worker }
523*38e8c45fSAndroid Build Coastguard Worker // Only track latency for events that originated from hardware
524*38e8c45fSAndroid Build Coastguard Worker if (eventEntry.isSynthesized()) {
525*38e8c45fSAndroid Build Coastguard Worker return false;
526*38e8c45fSAndroid Build Coastguard Worker }
527*38e8c45fSAndroid Build Coastguard Worker const EventEntry::Type& inputEventEntryType = eventEntry.type;
528*38e8c45fSAndroid Build Coastguard Worker if (inputEventEntryType == EventEntry::Type::KEY) {
529*38e8c45fSAndroid Build Coastguard Worker const KeyEntry& keyEntry = static_cast<const KeyEntry&>(eventEntry);
530*38e8c45fSAndroid Build Coastguard Worker if (keyEntry.flags & AKEY_EVENT_FLAG_CANCELED) {
531*38e8c45fSAndroid Build Coastguard Worker return false;
532*38e8c45fSAndroid Build Coastguard Worker }
533*38e8c45fSAndroid Build Coastguard Worker } else if (inputEventEntryType == EventEntry::Type::MOTION) {
534*38e8c45fSAndroid Build Coastguard Worker const MotionEntry& motionEntry = static_cast<const MotionEntry&>(eventEntry);
535*38e8c45fSAndroid Build Coastguard Worker if (motionEntry.action == AMOTION_EVENT_ACTION_CANCEL ||
536*38e8c45fSAndroid Build Coastguard Worker motionEntry.action == AMOTION_EVENT_ACTION_HOVER_EXIT) {
537*38e8c45fSAndroid Build Coastguard Worker return false;
538*38e8c45fSAndroid Build Coastguard Worker }
539*38e8c45fSAndroid Build Coastguard Worker } else {
540*38e8c45fSAndroid Build Coastguard Worker // Not a key or a motion
541*38e8c45fSAndroid Build Coastguard Worker return false;
542*38e8c45fSAndroid Build Coastguard Worker }
543*38e8c45fSAndroid Build Coastguard Worker if (!shouldReportMetricsForConnection(connection)) {
544*38e8c45fSAndroid Build Coastguard Worker return false;
545*38e8c45fSAndroid Build Coastguard Worker }
546*38e8c45fSAndroid Build Coastguard Worker return true;
547*38e8c45fSAndroid Build Coastguard Worker }
548*38e8c45fSAndroid Build Coastguard Worker
549*38e8c45fSAndroid Build Coastguard Worker /**
550*38e8c45fSAndroid Build Coastguard Worker * Connection is responsive if it has no events in the waitQueue that are older than the
551*38e8c45fSAndroid Build Coastguard Worker * current time.
552*38e8c45fSAndroid Build Coastguard Worker */
isConnectionResponsive(const Connection & connection)553*38e8c45fSAndroid Build Coastguard Worker bool isConnectionResponsive(const Connection& connection) {
554*38e8c45fSAndroid Build Coastguard Worker const nsecs_t currentTime = now();
555*38e8c45fSAndroid Build Coastguard Worker for (const auto& dispatchEntry : connection.waitQueue) {
556*38e8c45fSAndroid Build Coastguard Worker if (dispatchEntry->timeoutTime < currentTime) {
557*38e8c45fSAndroid Build Coastguard Worker return false;
558*38e8c45fSAndroid Build Coastguard Worker }
559*38e8c45fSAndroid Build Coastguard Worker }
560*38e8c45fSAndroid Build Coastguard Worker return true;
561*38e8c45fSAndroid Build Coastguard Worker }
562*38e8c45fSAndroid Build Coastguard Worker
563*38e8c45fSAndroid Build Coastguard Worker // Returns true if the event type passed as argument represents a user activity.
isUserActivityEvent(const EventEntry & eventEntry)564*38e8c45fSAndroid Build Coastguard Worker bool isUserActivityEvent(const EventEntry& eventEntry) {
565*38e8c45fSAndroid Build Coastguard Worker switch (eventEntry.type) {
566*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::DEVICE_RESET:
567*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::DRAG:
568*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::FOCUS:
569*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::POINTER_CAPTURE_CHANGED:
570*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::SENSOR:
571*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::TOUCH_MODE_CHANGED:
572*38e8c45fSAndroid Build Coastguard Worker return false;
573*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::KEY:
574*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::MOTION:
575*38e8c45fSAndroid Build Coastguard Worker return true;
576*38e8c45fSAndroid Build Coastguard Worker }
577*38e8c45fSAndroid Build Coastguard Worker }
578*38e8c45fSAndroid Build Coastguard Worker
579*38e8c45fSAndroid Build Coastguard Worker // Returns true if the given window can accept pointer events at the given display location.
windowAcceptsTouchAt(const WindowInfo & windowInfo,ui::LogicalDisplayId displayId,float x,float y,bool isStylus,const ui::Transform & displayTransform)580*38e8c45fSAndroid Build Coastguard Worker bool windowAcceptsTouchAt(const WindowInfo& windowInfo, ui::LogicalDisplayId displayId, float x,
581*38e8c45fSAndroid Build Coastguard Worker float y, bool isStylus, const ui::Transform& displayTransform) {
582*38e8c45fSAndroid Build Coastguard Worker const auto inputConfig = windowInfo.inputConfig;
583*38e8c45fSAndroid Build Coastguard Worker if (windowInfo.displayId != displayId ||
584*38e8c45fSAndroid Build Coastguard Worker inputConfig.test(WindowInfo::InputConfig::NOT_VISIBLE)) {
585*38e8c45fSAndroid Build Coastguard Worker return false;
586*38e8c45fSAndroid Build Coastguard Worker }
587*38e8c45fSAndroid Build Coastguard Worker const bool windowCanInterceptTouch = isStylus && windowInfo.interceptsStylus();
588*38e8c45fSAndroid Build Coastguard Worker if (inputConfig.test(WindowInfo::InputConfig::NOT_TOUCHABLE) && !windowCanInterceptTouch) {
589*38e8c45fSAndroid Build Coastguard Worker return false;
590*38e8c45fSAndroid Build Coastguard Worker }
591*38e8c45fSAndroid Build Coastguard Worker
592*38e8c45fSAndroid Build Coastguard Worker // Window Manager works in the logical display coordinate space. When it specifies bounds for a
593*38e8c45fSAndroid Build Coastguard Worker // window as (l, t, r, b), the range of x in [l, r) and y in [t, b) are considered to be inside
594*38e8c45fSAndroid Build Coastguard Worker // the window. Points on the right and bottom edges should not be inside the window, so we need
595*38e8c45fSAndroid Build Coastguard Worker // to be careful about performing a hit test when the display is rotated, since the "right" and
596*38e8c45fSAndroid Build Coastguard Worker // "bottom" of the window will be different in the display (un-rotated) space compared to in the
597*38e8c45fSAndroid Build Coastguard Worker // logical display in which WM determined the bounds. Perform the hit test in the logical
598*38e8c45fSAndroid Build Coastguard Worker // display space to ensure these edges are considered correctly in all orientations.
599*38e8c45fSAndroid Build Coastguard Worker const auto touchableRegion = displayTransform.transform(windowInfo.touchableRegion);
600*38e8c45fSAndroid Build Coastguard Worker const auto p = displayTransform.transform(x, y);
601*38e8c45fSAndroid Build Coastguard Worker if (!touchableRegion.contains(std::floor(p.x), std::floor(p.y))) {
602*38e8c45fSAndroid Build Coastguard Worker return false;
603*38e8c45fSAndroid Build Coastguard Worker }
604*38e8c45fSAndroid Build Coastguard Worker return true;
605*38e8c45fSAndroid Build Coastguard Worker }
606*38e8c45fSAndroid Build Coastguard Worker
607*38e8c45fSAndroid Build Coastguard Worker // Returns true if the given window's frame can occlude pointer events at the given display
608*38e8c45fSAndroid Build Coastguard Worker // location.
windowOccludesTouchAt(const WindowInfo & windowInfo,ui::LogicalDisplayId displayId,float x,float y,const ui::Transform & displayTransform)609*38e8c45fSAndroid Build Coastguard Worker bool windowOccludesTouchAt(const WindowInfo& windowInfo, ui::LogicalDisplayId displayId, float x,
610*38e8c45fSAndroid Build Coastguard Worker float y, const ui::Transform& displayTransform) {
611*38e8c45fSAndroid Build Coastguard Worker if (windowInfo.displayId != displayId) {
612*38e8c45fSAndroid Build Coastguard Worker return false;
613*38e8c45fSAndroid Build Coastguard Worker }
614*38e8c45fSAndroid Build Coastguard Worker const auto frame = displayTransform.transform(windowInfo.frame);
615*38e8c45fSAndroid Build Coastguard Worker const auto p = floor(displayTransform.transform(x, y));
616*38e8c45fSAndroid Build Coastguard Worker return p.x >= frame.left && p.x < frame.right && p.y >= frame.top && p.y < frame.bottom;
617*38e8c45fSAndroid Build Coastguard Worker }
618*38e8c45fSAndroid Build Coastguard Worker
isPointerFromStylus(const MotionEntry & entry,int32_t pointerIndex)619*38e8c45fSAndroid Build Coastguard Worker bool isPointerFromStylus(const MotionEntry& entry, int32_t pointerIndex) {
620*38e8c45fSAndroid Build Coastguard Worker return isFromSource(entry.source, AINPUT_SOURCE_STYLUS) &&
621*38e8c45fSAndroid Build Coastguard Worker isStylusToolType(entry.pointerProperties[pointerIndex].toolType);
622*38e8c45fSAndroid Build Coastguard Worker }
623*38e8c45fSAndroid Build Coastguard Worker
624*38e8c45fSAndroid Build Coastguard Worker // Determines if the given window can be targeted as InputTarget::Flags::FOREGROUND.
625*38e8c45fSAndroid Build Coastguard Worker // Foreground events are only sent to "foreground targetable" windows, but not all gestures sent to
626*38e8c45fSAndroid Build Coastguard Worker // such window are necessarily targeted with the flag. For example, an event with ACTION_OUTSIDE can
627*38e8c45fSAndroid Build Coastguard Worker // be sent to such a window, but it is not a foreground event and doesn't use
628*38e8c45fSAndroid Build Coastguard Worker // InputTarget::Flags::FOREGROUND.
canReceiveForegroundTouches(const WindowInfo & info)629*38e8c45fSAndroid Build Coastguard Worker bool canReceiveForegroundTouches(const WindowInfo& info) {
630*38e8c45fSAndroid Build Coastguard Worker // A non-touchable window can still receive touch events (e.g. in the case of
631*38e8c45fSAndroid Build Coastguard Worker // STYLUS_INTERCEPTOR), so prevent such windows from receiving foreground events for touches.
632*38e8c45fSAndroid Build Coastguard Worker return !info.inputConfig.test(gui::WindowInfo::InputConfig::NOT_TOUCHABLE) && !info.isSpy();
633*38e8c45fSAndroid Build Coastguard Worker }
634*38e8c45fSAndroid Build Coastguard Worker
isWindowOwnedBy(const sp<WindowInfoHandle> & windowHandle,gui::Pid pid,gui::Uid uid)635*38e8c45fSAndroid Build Coastguard Worker bool isWindowOwnedBy(const sp<WindowInfoHandle>& windowHandle, gui::Pid pid, gui::Uid uid) {
636*38e8c45fSAndroid Build Coastguard Worker if (windowHandle == nullptr) {
637*38e8c45fSAndroid Build Coastguard Worker return false;
638*38e8c45fSAndroid Build Coastguard Worker }
639*38e8c45fSAndroid Build Coastguard Worker const WindowInfo* windowInfo = windowHandle->getInfo();
640*38e8c45fSAndroid Build Coastguard Worker if (pid == windowInfo->ownerPid && uid == windowInfo->ownerUid) {
641*38e8c45fSAndroid Build Coastguard Worker return true;
642*38e8c45fSAndroid Build Coastguard Worker }
643*38e8c45fSAndroid Build Coastguard Worker return false;
644*38e8c45fSAndroid Build Coastguard Worker }
645*38e8c45fSAndroid Build Coastguard Worker
646*38e8c45fSAndroid Build Coastguard Worker // Checks targeted injection using the window's owner's uid.
647*38e8c45fSAndroid Build Coastguard Worker // Returns an empty string if an entry can be sent to the given window, or an error message if the
648*38e8c45fSAndroid Build Coastguard Worker // entry is a targeted injection whose uid target doesn't match the window owner.
verifyTargetedInjection(const sp<WindowInfoHandle> & window,const EventEntry & entry)649*38e8c45fSAndroid Build Coastguard Worker std::optional<std::string> verifyTargetedInjection(const sp<WindowInfoHandle>& window,
650*38e8c45fSAndroid Build Coastguard Worker const EventEntry& entry) {
651*38e8c45fSAndroid Build Coastguard Worker if (entry.injectionState == nullptr || !entry.injectionState->targetUid) {
652*38e8c45fSAndroid Build Coastguard Worker // The event was not injected, or the injected event does not target a window.
653*38e8c45fSAndroid Build Coastguard Worker return {};
654*38e8c45fSAndroid Build Coastguard Worker }
655*38e8c45fSAndroid Build Coastguard Worker const auto uid = *entry.injectionState->targetUid;
656*38e8c45fSAndroid Build Coastguard Worker if (window == nullptr) {
657*38e8c45fSAndroid Build Coastguard Worker return StringPrintf("No valid window target for injection into uid %s.",
658*38e8c45fSAndroid Build Coastguard Worker uid.toString().c_str());
659*38e8c45fSAndroid Build Coastguard Worker }
660*38e8c45fSAndroid Build Coastguard Worker if (entry.injectionState->targetUid != window->getInfo()->ownerUid) {
661*38e8c45fSAndroid Build Coastguard Worker return StringPrintf("Injected event targeted at uid %s would be dispatched to window '%s' "
662*38e8c45fSAndroid Build Coastguard Worker "owned by uid %s.",
663*38e8c45fSAndroid Build Coastguard Worker uid.toString().c_str(), window->getName().c_str(),
664*38e8c45fSAndroid Build Coastguard Worker window->getInfo()->ownerUid.toString().c_str());
665*38e8c45fSAndroid Build Coastguard Worker }
666*38e8c45fSAndroid Build Coastguard Worker return {};
667*38e8c45fSAndroid Build Coastguard Worker }
668*38e8c45fSAndroid Build Coastguard Worker
resolveTouchedPosition(const MotionEntry & entry)669*38e8c45fSAndroid Build Coastguard Worker std::pair<float, float> resolveTouchedPosition(const MotionEntry& entry) {
670*38e8c45fSAndroid Build Coastguard Worker const bool isFromMouse = isFromSource(entry.source, AINPUT_SOURCE_MOUSE);
671*38e8c45fSAndroid Build Coastguard Worker // Always dispatch mouse events to cursor position.
672*38e8c45fSAndroid Build Coastguard Worker if (isFromMouse) {
673*38e8c45fSAndroid Build Coastguard Worker return {entry.xCursorPosition, entry.yCursorPosition};
674*38e8c45fSAndroid Build Coastguard Worker }
675*38e8c45fSAndroid Build Coastguard Worker
676*38e8c45fSAndroid Build Coastguard Worker const int32_t pointerIndex = MotionEvent::getActionIndex(entry.action);
677*38e8c45fSAndroid Build Coastguard Worker return {entry.pointerCoords[pointerIndex].getAxisValue(AMOTION_EVENT_AXIS_X),
678*38e8c45fSAndroid Build Coastguard Worker entry.pointerCoords[pointerIndex].getAxisValue(AMOTION_EVENT_AXIS_Y)};
679*38e8c45fSAndroid Build Coastguard Worker }
680*38e8c45fSAndroid Build Coastguard Worker
getDownTime(const EventEntry & eventEntry)681*38e8c45fSAndroid Build Coastguard Worker std::optional<nsecs_t> getDownTime(const EventEntry& eventEntry) {
682*38e8c45fSAndroid Build Coastguard Worker if (eventEntry.type == EventEntry::Type::KEY) {
683*38e8c45fSAndroid Build Coastguard Worker const KeyEntry& keyEntry = static_cast<const KeyEntry&>(eventEntry);
684*38e8c45fSAndroid Build Coastguard Worker return keyEntry.downTime;
685*38e8c45fSAndroid Build Coastguard Worker } else if (eventEntry.type == EventEntry::Type::MOTION) {
686*38e8c45fSAndroid Build Coastguard Worker const MotionEntry& motionEntry = static_cast<const MotionEntry&>(eventEntry);
687*38e8c45fSAndroid Build Coastguard Worker return motionEntry.downTime;
688*38e8c45fSAndroid Build Coastguard Worker }
689*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
690*38e8c45fSAndroid Build Coastguard Worker }
691*38e8c45fSAndroid Build Coastguard Worker
692*38e8c45fSAndroid Build Coastguard Worker /**
693*38e8c45fSAndroid Build Coastguard Worker * Compare the old touch state to the new touch state, and generate the corresponding touched
694*38e8c45fSAndroid Build Coastguard Worker * windows (== input targets).
695*38e8c45fSAndroid Build Coastguard Worker * If a window had the hovering pointer, but now it doesn't, produce HOVER_EXIT for that window.
696*38e8c45fSAndroid Build Coastguard Worker * If the pointer just entered the new window, produce HOVER_ENTER.
697*38e8c45fSAndroid Build Coastguard Worker * For pointers remaining in the window, produce HOVER_MOVE.
698*38e8c45fSAndroid Build Coastguard Worker */
getHoveringWindowsLocked(const TouchState * oldState,const TouchState & newTouchState,const MotionEntry & entry,std::function<void ()> dump)699*38e8c45fSAndroid Build Coastguard Worker std::vector<TouchedWindow> getHoveringWindowsLocked(const TouchState* oldState,
700*38e8c45fSAndroid Build Coastguard Worker const TouchState& newTouchState,
701*38e8c45fSAndroid Build Coastguard Worker const MotionEntry& entry,
702*38e8c45fSAndroid Build Coastguard Worker std::function<void()> dump) {
703*38e8c45fSAndroid Build Coastguard Worker const int32_t maskedAction = MotionEvent::getActionMasked(entry.action);
704*38e8c45fSAndroid Build Coastguard Worker
705*38e8c45fSAndroid Build Coastguard Worker if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) {
706*38e8c45fSAndroid Build Coastguard Worker // ACTION_SCROLL events should not affect the hovering pointer dispatch
707*38e8c45fSAndroid Build Coastguard Worker return {};
708*38e8c45fSAndroid Build Coastguard Worker }
709*38e8c45fSAndroid Build Coastguard Worker std::vector<TouchedWindow> out;
710*38e8c45fSAndroid Build Coastguard Worker
711*38e8c45fSAndroid Build Coastguard Worker // We should consider all hovering pointers here. But for now, just use the first one
712*38e8c45fSAndroid Build Coastguard Worker const PointerProperties& pointer = entry.pointerProperties[0];
713*38e8c45fSAndroid Build Coastguard Worker
714*38e8c45fSAndroid Build Coastguard Worker std::set<sp<WindowInfoHandle>> oldWindows;
715*38e8c45fSAndroid Build Coastguard Worker if (oldState != nullptr) {
716*38e8c45fSAndroid Build Coastguard Worker oldWindows = oldState->getWindowsWithHoveringPointer(entry.deviceId, pointer.id);
717*38e8c45fSAndroid Build Coastguard Worker }
718*38e8c45fSAndroid Build Coastguard Worker
719*38e8c45fSAndroid Build Coastguard Worker std::set<sp<WindowInfoHandle>> newWindows =
720*38e8c45fSAndroid Build Coastguard Worker newTouchState.getWindowsWithHoveringPointer(entry.deviceId, pointer.id);
721*38e8c45fSAndroid Build Coastguard Worker
722*38e8c45fSAndroid Build Coastguard Worker // If the pointer is no longer in the new window set, send HOVER_EXIT.
723*38e8c45fSAndroid Build Coastguard Worker for (const sp<WindowInfoHandle>& oldWindow : oldWindows) {
724*38e8c45fSAndroid Build Coastguard Worker if (newWindows.find(oldWindow) == newWindows.end()) {
725*38e8c45fSAndroid Build Coastguard Worker TouchedWindow touchedWindow;
726*38e8c45fSAndroid Build Coastguard Worker touchedWindow.windowHandle = oldWindow;
727*38e8c45fSAndroid Build Coastguard Worker touchedWindow.dispatchMode = InputTarget::DispatchMode::HOVER_EXIT;
728*38e8c45fSAndroid Build Coastguard Worker out.push_back(touchedWindow);
729*38e8c45fSAndroid Build Coastguard Worker }
730*38e8c45fSAndroid Build Coastguard Worker }
731*38e8c45fSAndroid Build Coastguard Worker
732*38e8c45fSAndroid Build Coastguard Worker for (const sp<WindowInfoHandle>& newWindow : newWindows) {
733*38e8c45fSAndroid Build Coastguard Worker TouchedWindow touchedWindow;
734*38e8c45fSAndroid Build Coastguard Worker touchedWindow.windowHandle = newWindow;
735*38e8c45fSAndroid Build Coastguard Worker if (oldWindows.find(newWindow) == oldWindows.end()) {
736*38e8c45fSAndroid Build Coastguard Worker // Any windows that have this pointer now, and didn't have it before, should get
737*38e8c45fSAndroid Build Coastguard Worker // HOVER_ENTER
738*38e8c45fSAndroid Build Coastguard Worker touchedWindow.dispatchMode = InputTarget::DispatchMode::HOVER_ENTER;
739*38e8c45fSAndroid Build Coastguard Worker } else {
740*38e8c45fSAndroid Build Coastguard Worker // This pointer was already sent to the window. Use ACTION_HOVER_MOVE.
741*38e8c45fSAndroid Build Coastguard Worker if (CC_UNLIKELY(maskedAction != AMOTION_EVENT_ACTION_HOVER_MOVE)) {
742*38e8c45fSAndroid Build Coastguard Worker android::base::LogSeverity severity = android::base::LogSeverity::FATAL;
743*38e8c45fSAndroid Build Coastguard Worker if (!input_flags::a11y_crash_on_inconsistent_event_stream() &&
744*38e8c45fSAndroid Build Coastguard Worker entry.flags & AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT) {
745*38e8c45fSAndroid Build Coastguard Worker // The Accessibility injected touch exploration event stream
746*38e8c45fSAndroid Build Coastguard Worker // has known inconsistencies, so log ERROR instead of
747*38e8c45fSAndroid Build Coastguard Worker // crashing the device with FATAL.
748*38e8c45fSAndroid Build Coastguard Worker severity = android::base::LogSeverity::ERROR;
749*38e8c45fSAndroid Build Coastguard Worker }
750*38e8c45fSAndroid Build Coastguard Worker dump();
751*38e8c45fSAndroid Build Coastguard Worker LOG(severity) << "Expected ACTION_HOVER_MOVE instead of " << entry.getDescription();
752*38e8c45fSAndroid Build Coastguard Worker }
753*38e8c45fSAndroid Build Coastguard Worker touchedWindow.dispatchMode = InputTarget::DispatchMode::AS_IS;
754*38e8c45fSAndroid Build Coastguard Worker }
755*38e8c45fSAndroid Build Coastguard Worker const auto [x, y] = resolveTouchedPosition(entry);
756*38e8c45fSAndroid Build Coastguard Worker touchedWindow.addHoveringPointer(entry.deviceId, pointer, x, y);
757*38e8c45fSAndroid Build Coastguard Worker if (canReceiveForegroundTouches(*newWindow->getInfo())) {
758*38e8c45fSAndroid Build Coastguard Worker touchedWindow.targetFlags |= InputTarget::Flags::FOREGROUND;
759*38e8c45fSAndroid Build Coastguard Worker }
760*38e8c45fSAndroid Build Coastguard Worker out.push_back(touchedWindow);
761*38e8c45fSAndroid Build Coastguard Worker }
762*38e8c45fSAndroid Build Coastguard Worker return out;
763*38e8c45fSAndroid Build Coastguard Worker }
764*38e8c45fSAndroid Build Coastguard Worker
765*38e8c45fSAndroid Build Coastguard Worker template <typename T>
operator +=(std::vector<T> & left,const std::vector<T> & right)766*38e8c45fSAndroid Build Coastguard Worker std::vector<T>& operator+=(std::vector<T>& left, const std::vector<T>& right) {
767*38e8c45fSAndroid Build Coastguard Worker left.insert(left.end(), right.begin(), right.end());
768*38e8c45fSAndroid Build Coastguard Worker return left;
769*38e8c45fSAndroid Build Coastguard Worker }
770*38e8c45fSAndroid Build Coastguard Worker
771*38e8c45fSAndroid Build Coastguard Worker // Filter windows in a TouchState and targets in a vector to remove untrusted windows/targets from
772*38e8c45fSAndroid Build Coastguard Worker // both.
filterUntrustedTargets(TouchState & touchState,std::vector<InputTarget> & targets)773*38e8c45fSAndroid Build Coastguard Worker void filterUntrustedTargets(TouchState& touchState, std::vector<InputTarget>& targets) {
774*38e8c45fSAndroid Build Coastguard Worker std::erase_if(touchState.windows, [&](const TouchedWindow& window) {
775*38e8c45fSAndroid Build Coastguard Worker if (!window.windowHandle->getInfo()->inputConfig.test(
776*38e8c45fSAndroid Build Coastguard Worker WindowInfo::InputConfig::TRUSTED_OVERLAY)) {
777*38e8c45fSAndroid Build Coastguard Worker // In addition to TouchState, erase this window from the input targets! We don't have a
778*38e8c45fSAndroid Build Coastguard Worker // good way to do this today except by adding a nested loop.
779*38e8c45fSAndroid Build Coastguard Worker // TODO(b/282025641): simplify this code once InputTargets are being identified
780*38e8c45fSAndroid Build Coastguard Worker // separately from TouchedWindows.
781*38e8c45fSAndroid Build Coastguard Worker std::erase_if(targets, [&](const InputTarget& target) {
782*38e8c45fSAndroid Build Coastguard Worker return target.connection->getToken() == window.windowHandle->getToken();
783*38e8c45fSAndroid Build Coastguard Worker });
784*38e8c45fSAndroid Build Coastguard Worker return true;
785*38e8c45fSAndroid Build Coastguard Worker }
786*38e8c45fSAndroid Build Coastguard Worker return false;
787*38e8c45fSAndroid Build Coastguard Worker });
788*38e8c45fSAndroid Build Coastguard Worker }
789*38e8c45fSAndroid Build Coastguard Worker
790*38e8c45fSAndroid Build Coastguard Worker /**
791*38e8c45fSAndroid Build Coastguard Worker * In general, touch should be always split between windows. Some exceptions:
792*38e8c45fSAndroid Build Coastguard Worker * 1. Don't split touch if all of the below is true:
793*38e8c45fSAndroid Build Coastguard Worker * (a) we have an active pointer down *and*
794*38e8c45fSAndroid Build Coastguard Worker * (b) a new pointer is going down that's from the same device *and*
795*38e8c45fSAndroid Build Coastguard Worker * (c) the window that's receiving the current pointer does not support split touch.
796*38e8c45fSAndroid Build Coastguard Worker * 2. Don't split mouse events
797*38e8c45fSAndroid Build Coastguard Worker */
shouldSplitTouch(const TouchState & touchState,const MotionEntry & entry)798*38e8c45fSAndroid Build Coastguard Worker bool shouldSplitTouch(const TouchState& touchState, const MotionEntry& entry) {
799*38e8c45fSAndroid Build Coastguard Worker if (isFromSource(entry.source, AINPUT_SOURCE_MOUSE)) {
800*38e8c45fSAndroid Build Coastguard Worker // We should never split mouse events
801*38e8c45fSAndroid Build Coastguard Worker return false;
802*38e8c45fSAndroid Build Coastguard Worker }
803*38e8c45fSAndroid Build Coastguard Worker for (const TouchedWindow& touchedWindow : touchState.windows) {
804*38e8c45fSAndroid Build Coastguard Worker if (touchedWindow.windowHandle->getInfo()->isSpy()) {
805*38e8c45fSAndroid Build Coastguard Worker // Spy windows should not affect whether or not touch is split.
806*38e8c45fSAndroid Build Coastguard Worker continue;
807*38e8c45fSAndroid Build Coastguard Worker }
808*38e8c45fSAndroid Build Coastguard Worker if (touchedWindow.windowHandle->getInfo()->supportsSplitTouch()) {
809*38e8c45fSAndroid Build Coastguard Worker continue;
810*38e8c45fSAndroid Build Coastguard Worker }
811*38e8c45fSAndroid Build Coastguard Worker if (touchedWindow.windowHandle->getInfo()->inputConfig.test(
812*38e8c45fSAndroid Build Coastguard Worker gui::WindowInfo::InputConfig::IS_WALLPAPER)) {
813*38e8c45fSAndroid Build Coastguard Worker // Wallpaper window should not affect whether or not touch is split
814*38e8c45fSAndroid Build Coastguard Worker continue;
815*38e8c45fSAndroid Build Coastguard Worker }
816*38e8c45fSAndroid Build Coastguard Worker
817*38e8c45fSAndroid Build Coastguard Worker if (touchedWindow.hasTouchingPointers(entry.deviceId)) {
818*38e8c45fSAndroid Build Coastguard Worker return false;
819*38e8c45fSAndroid Build Coastguard Worker }
820*38e8c45fSAndroid Build Coastguard Worker }
821*38e8c45fSAndroid Build Coastguard Worker return true;
822*38e8c45fSAndroid Build Coastguard Worker }
823*38e8c45fSAndroid Build Coastguard Worker
824*38e8c45fSAndroid Build Coastguard Worker /**
825*38e8c45fSAndroid Build Coastguard Worker * Return true if stylus is currently down anywhere on the specified display, and false otherwise.
826*38e8c45fSAndroid Build Coastguard Worker */
isStylusActiveInDisplay(ui::LogicalDisplayId displayId,const std::unordered_map<ui::LogicalDisplayId,TouchState> & touchStatesByDisplay)827*38e8c45fSAndroid Build Coastguard Worker bool isStylusActiveInDisplay(ui::LogicalDisplayId displayId,
828*38e8c45fSAndroid Build Coastguard Worker const std::unordered_map<ui::LogicalDisplayId /*displayId*/,
829*38e8c45fSAndroid Build Coastguard Worker TouchState>& touchStatesByDisplay) {
830*38e8c45fSAndroid Build Coastguard Worker const auto it = touchStatesByDisplay.find(displayId);
831*38e8c45fSAndroid Build Coastguard Worker if (it == touchStatesByDisplay.end()) {
832*38e8c45fSAndroid Build Coastguard Worker return false;
833*38e8c45fSAndroid Build Coastguard Worker }
834*38e8c45fSAndroid Build Coastguard Worker const TouchState& state = it->second;
835*38e8c45fSAndroid Build Coastguard Worker return state.hasActiveStylus();
836*38e8c45fSAndroid Build Coastguard Worker }
837*38e8c45fSAndroid Build Coastguard Worker
validateWindowInfosUpdate(const gui::WindowInfosUpdate & update)838*38e8c45fSAndroid Build Coastguard Worker Result<void> validateWindowInfosUpdate(const gui::WindowInfosUpdate& update) {
839*38e8c45fSAndroid Build Coastguard Worker std::unordered_set<int32_t> windowIds;
840*38e8c45fSAndroid Build Coastguard Worker for (const WindowInfo& info : update.windowInfos) {
841*38e8c45fSAndroid Build Coastguard Worker const auto [_, inserted] = windowIds.insert(info.id);
842*38e8c45fSAndroid Build Coastguard Worker if (!inserted) {
843*38e8c45fSAndroid Build Coastguard Worker return Error() << "Duplicate entry for " << info;
844*38e8c45fSAndroid Build Coastguard Worker }
845*38e8c45fSAndroid Build Coastguard Worker }
846*38e8c45fSAndroid Build Coastguard Worker return {};
847*38e8c45fSAndroid Build Coastguard Worker }
848*38e8c45fSAndroid Build Coastguard Worker
getUserActivityEventType(const EventEntry & eventEntry)849*38e8c45fSAndroid Build Coastguard Worker int32_t getUserActivityEventType(const EventEntry& eventEntry) {
850*38e8c45fSAndroid Build Coastguard Worker switch (eventEntry.type) {
851*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::KEY: {
852*38e8c45fSAndroid Build Coastguard Worker return USER_ACTIVITY_EVENT_BUTTON;
853*38e8c45fSAndroid Build Coastguard Worker }
854*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::MOTION: {
855*38e8c45fSAndroid Build Coastguard Worker const MotionEntry& motionEntry = static_cast<const MotionEntry&>(eventEntry);
856*38e8c45fSAndroid Build Coastguard Worker if (MotionEvent::isTouchEvent(motionEntry.source, motionEntry.action)) {
857*38e8c45fSAndroid Build Coastguard Worker return USER_ACTIVITY_EVENT_TOUCH;
858*38e8c45fSAndroid Build Coastguard Worker }
859*38e8c45fSAndroid Build Coastguard Worker return USER_ACTIVITY_EVENT_OTHER;
860*38e8c45fSAndroid Build Coastguard Worker }
861*38e8c45fSAndroid Build Coastguard Worker default: {
862*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("%s events are not user activity",
863*38e8c45fSAndroid Build Coastguard Worker ftl::enum_string(eventEntry.type).c_str());
864*38e8c45fSAndroid Build Coastguard Worker }
865*38e8c45fSAndroid Build Coastguard Worker }
866*38e8c45fSAndroid Build Coastguard Worker }
867*38e8c45fSAndroid Build Coastguard Worker
expandCancellationMode(CancelationOptions::Mode mode)868*38e8c45fSAndroid Build Coastguard Worker std::pair<bool /*cancelPointers*/, bool /*cancelNonPointers*/> expandCancellationMode(
869*38e8c45fSAndroid Build Coastguard Worker CancelationOptions::Mode mode) {
870*38e8c45fSAndroid Build Coastguard Worker switch (mode) {
871*38e8c45fSAndroid Build Coastguard Worker case CancelationOptions::Mode::CANCEL_ALL_EVENTS:
872*38e8c45fSAndroid Build Coastguard Worker return {true, true};
873*38e8c45fSAndroid Build Coastguard Worker case CancelationOptions::Mode::CANCEL_POINTER_EVENTS:
874*38e8c45fSAndroid Build Coastguard Worker return {true, false};
875*38e8c45fSAndroid Build Coastguard Worker case CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS:
876*38e8c45fSAndroid Build Coastguard Worker return {false, true};
877*38e8c45fSAndroid Build Coastguard Worker case CancelationOptions::Mode::CANCEL_FALLBACK_EVENTS:
878*38e8c45fSAndroid Build Coastguard Worker return {false, true};
879*38e8c45fSAndroid Build Coastguard Worker case CancelationOptions::Mode::CANCEL_HOVER_EVENTS:
880*38e8c45fSAndroid Build Coastguard Worker return {true, false};
881*38e8c45fSAndroid Build Coastguard Worker }
882*38e8c45fSAndroid Build Coastguard Worker }
883*38e8c45fSAndroid Build Coastguard Worker
884*38e8c45fSAndroid Build Coastguard Worker class ScopedSyntheticEventTracer {
885*38e8c45fSAndroid Build Coastguard Worker public:
ScopedSyntheticEventTracer(std::unique_ptr<trace::InputTracerInterface> & tracer)886*38e8c45fSAndroid Build Coastguard Worker ScopedSyntheticEventTracer(std::unique_ptr<trace::InputTracerInterface>& tracer)
887*38e8c45fSAndroid Build Coastguard Worker : mTracer(tracer), mProcessingTimestamp(now()) {
888*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
889*38e8c45fSAndroid Build Coastguard Worker mEventTracker = mTracer->createTrackerForSyntheticEvent();
890*38e8c45fSAndroid Build Coastguard Worker }
891*38e8c45fSAndroid Build Coastguard Worker }
892*38e8c45fSAndroid Build Coastguard Worker
~ScopedSyntheticEventTracer()893*38e8c45fSAndroid Build Coastguard Worker ~ScopedSyntheticEventTracer() {
894*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
895*38e8c45fSAndroid Build Coastguard Worker mTracer->eventProcessingComplete(*mEventTracker, mProcessingTimestamp);
896*38e8c45fSAndroid Build Coastguard Worker }
897*38e8c45fSAndroid Build Coastguard Worker }
898*38e8c45fSAndroid Build Coastguard Worker
getTracker() const899*38e8c45fSAndroid Build Coastguard Worker const std::unique_ptr<trace::EventTrackerInterface>& getTracker() const {
900*38e8c45fSAndroid Build Coastguard Worker return mEventTracker;
901*38e8c45fSAndroid Build Coastguard Worker }
902*38e8c45fSAndroid Build Coastguard Worker
903*38e8c45fSAndroid Build Coastguard Worker private:
904*38e8c45fSAndroid Build Coastguard Worker const std::unique_ptr<trace::InputTracerInterface>& mTracer;
905*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<trace::EventTrackerInterface> mEventTracker;
906*38e8c45fSAndroid Build Coastguard Worker const nsecs_t mProcessingTimestamp;
907*38e8c45fSAndroid Build Coastguard Worker };
908*38e8c45fSAndroid Build Coastguard Worker
909*38e8c45fSAndroid Build Coastguard Worker /**
910*38e8c45fSAndroid Build Coastguard Worker * This is needed to help use "InputEventInjectionResult" with base::Result.
911*38e8c45fSAndroid Build Coastguard Worker */
912*38e8c45fSAndroid Build Coastguard Worker template <typename T>
913*38e8c45fSAndroid Build Coastguard Worker struct EnumErrorWrapper {
914*38e8c45fSAndroid Build Coastguard Worker T mVal;
EnumErrorWrapperandroid::inputdispatcher::__anond529f6320111::EnumErrorWrapper915*38e8c45fSAndroid Build Coastguard Worker EnumErrorWrapper(T&& e) : mVal(std::forward<T>(e)) {}
operator const T&android::inputdispatcher::__anond529f6320111::EnumErrorWrapper916*38e8c45fSAndroid Build Coastguard Worker operator const T&() const { return mVal; }
valueandroid::inputdispatcher::__anond529f6320111::EnumErrorWrapper917*38e8c45fSAndroid Build Coastguard Worker T value() const { return mVal; }
printandroid::inputdispatcher::__anond529f6320111::EnumErrorWrapper918*38e8c45fSAndroid Build Coastguard Worker std::string print() const { return ftl::enum_string(mVal); }
919*38e8c45fSAndroid Build Coastguard Worker };
920*38e8c45fSAndroid Build Coastguard Worker
injectionError(InputEventInjectionResult && e)921*38e8c45fSAndroid Build Coastguard Worker Error<EnumErrorWrapper<InputEventInjectionResult>> injectionError(InputEventInjectionResult&& e) {
922*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(e == InputEventInjectionResult::SUCCEEDED);
923*38e8c45fSAndroid Build Coastguard Worker return Error<EnumErrorWrapper<InputEventInjectionResult>>(
924*38e8c45fSAndroid Build Coastguard Worker std::forward<InputEventInjectionResult>(e));
925*38e8c45fSAndroid Build Coastguard Worker }
926*38e8c45fSAndroid Build Coastguard Worker
927*38e8c45fSAndroid Build Coastguard Worker } // namespace
928*38e8c45fSAndroid Build Coastguard Worker
929*38e8c45fSAndroid Build Coastguard Worker // --- InputDispatcher ---
930*38e8c45fSAndroid Build Coastguard Worker
InputDispatcher(InputDispatcherPolicyInterface & policy)931*38e8c45fSAndroid Build Coastguard Worker InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy)
932*38e8c45fSAndroid Build Coastguard Worker : InputDispatcher(policy, createInputTracingBackendIfEnabled()) {}
933*38e8c45fSAndroid Build Coastguard Worker
InputDispatcher(InputDispatcherPolicyInterface & policy,std::unique_ptr<trace::InputTracingBackendInterface> traceBackend)934*38e8c45fSAndroid Build Coastguard Worker InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy,
935*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<trace::InputTracingBackendInterface> traceBackend)
936*38e8c45fSAndroid Build Coastguard Worker : mPolicy(policy),
937*38e8c45fSAndroid Build Coastguard Worker mPendingEvent(nullptr),
938*38e8c45fSAndroid Build Coastguard Worker mLastDropReason(DropReason::NOT_DROPPED),
939*38e8c45fSAndroid Build Coastguard Worker mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER),
940*38e8c45fSAndroid Build Coastguard Worker mMinTimeBetweenUserActivityPokes(DEFAULT_USER_ACTIVITY_POKE_INTERVAL),
941*38e8c45fSAndroid Build Coastguard Worker mNextUnblockedEvent(nullptr),
942*38e8c45fSAndroid Build Coastguard Worker mMonitorDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT),
943*38e8c45fSAndroid Build Coastguard Worker mDispatchEnabled(false),
944*38e8c45fSAndroid Build Coastguard Worker mDispatchFrozen(false),
945*38e8c45fSAndroid Build Coastguard Worker mInputFilterEnabled(false),
946*38e8c45fSAndroid Build Coastguard Worker mMaximumObscuringOpacityForTouch(1.0f),
947*38e8c45fSAndroid Build Coastguard Worker mFocusedDisplayId(ui::LogicalDisplayId::DEFAULT),
948*38e8c45fSAndroid Build Coastguard Worker mWindowTokenWithPointerCapture(nullptr),
949*38e8c45fSAndroid Build Coastguard Worker mAwaitedApplicationDisplayId(ui::LogicalDisplayId::INVALID),
950*38e8c45fSAndroid Build Coastguard Worker mInputEventTimelineProcessor(
951*38e8c45fSAndroid Build Coastguard Worker input_flags::enable_per_device_input_latency_metrics()
952*38e8c45fSAndroid Build Coastguard Worker ? std::move(std::unique_ptr<InputEventTimelineProcessor>(
953*38e8c45fSAndroid Build Coastguard Worker new LatencyAggregatorWithHistograms()))
954*38e8c45fSAndroid Build Coastguard Worker : std::move(std::unique_ptr<InputEventTimelineProcessor>(
955*38e8c45fSAndroid Build Coastguard Worker new LatencyAggregator()))),
956*38e8c45fSAndroid Build Coastguard Worker mLatencyTracker(*mInputEventTimelineProcessor) {
957*38e8c45fSAndroid Build Coastguard Worker mLooper = sp<Looper>::make(false);
958*38e8c45fSAndroid Build Coastguard Worker mReporter = createInputReporter();
959*38e8c45fSAndroid Build Coastguard Worker
960*38e8c45fSAndroid Build Coastguard Worker mWindowInfoListener = sp<DispatcherWindowListener>::make(*this);
961*38e8c45fSAndroid Build Coastguard Worker #if defined(__ANDROID__)
962*38e8c45fSAndroid Build Coastguard Worker SurfaceComposerClient::getDefault()->addWindowInfosListener(mWindowInfoListener);
963*38e8c45fSAndroid Build Coastguard Worker #endif
964*38e8c45fSAndroid Build Coastguard Worker mKeyRepeatState.lastKeyEntry = nullptr;
965*38e8c45fSAndroid Build Coastguard Worker
966*38e8c45fSAndroid Build Coastguard Worker if (traceBackend) {
967*38e8c45fSAndroid Build Coastguard Worker mTracer = std::make_unique<trace::impl::InputTracer>(std::move(traceBackend));
968*38e8c45fSAndroid Build Coastguard Worker }
969*38e8c45fSAndroid Build Coastguard Worker
970*38e8c45fSAndroid Build Coastguard Worker mLastUserActivityTimes.fill(0);
971*38e8c45fSAndroid Build Coastguard Worker }
972*38e8c45fSAndroid Build Coastguard Worker
~InputDispatcher()973*38e8c45fSAndroid Build Coastguard Worker InputDispatcher::~InputDispatcher() {
974*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
975*38e8c45fSAndroid Build Coastguard Worker
976*38e8c45fSAndroid Build Coastguard Worker resetKeyRepeatLocked();
977*38e8c45fSAndroid Build Coastguard Worker releasePendingEventLocked();
978*38e8c45fSAndroid Build Coastguard Worker drainInboundQueueLocked();
979*38e8c45fSAndroid Build Coastguard Worker mCommandQueue.clear();
980*38e8c45fSAndroid Build Coastguard Worker
981*38e8c45fSAndroid Build Coastguard Worker while (!mConnectionsByToken.empty()) {
982*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<Connection> connection = mConnectionsByToken.begin()->second;
983*38e8c45fSAndroid Build Coastguard Worker removeInputChannelLocked(connection->getToken(), /*notify=*/false);
984*38e8c45fSAndroid Build Coastguard Worker }
985*38e8c45fSAndroid Build Coastguard Worker }
986*38e8c45fSAndroid Build Coastguard Worker
start()987*38e8c45fSAndroid Build Coastguard Worker status_t InputDispatcher::start() {
988*38e8c45fSAndroid Build Coastguard Worker if (mThread) {
989*38e8c45fSAndroid Build Coastguard Worker return ALREADY_EXISTS;
990*38e8c45fSAndroid Build Coastguard Worker }
991*38e8c45fSAndroid Build Coastguard Worker mThread = std::make_unique<InputThread>(
992*38e8c45fSAndroid Build Coastguard Worker "InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); },
993*38e8c45fSAndroid Build Coastguard Worker /*isInCriticalPath=*/true);
994*38e8c45fSAndroid Build Coastguard Worker return OK;
995*38e8c45fSAndroid Build Coastguard Worker }
996*38e8c45fSAndroid Build Coastguard Worker
stop()997*38e8c45fSAndroid Build Coastguard Worker status_t InputDispatcher::stop() {
998*38e8c45fSAndroid Build Coastguard Worker if (mThread && mThread->isCallingThread()) {
999*38e8c45fSAndroid Build Coastguard Worker ALOGE("InputDispatcher cannot be stopped from its own thread!");
1000*38e8c45fSAndroid Build Coastguard Worker return INVALID_OPERATION;
1001*38e8c45fSAndroid Build Coastguard Worker }
1002*38e8c45fSAndroid Build Coastguard Worker mThread.reset();
1003*38e8c45fSAndroid Build Coastguard Worker return OK;
1004*38e8c45fSAndroid Build Coastguard Worker }
1005*38e8c45fSAndroid Build Coastguard Worker
dispatchOnce()1006*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::dispatchOnce() {
1007*38e8c45fSAndroid Build Coastguard Worker nsecs_t nextWakeupTime = LLONG_MAX;
1008*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
1009*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
1010*38e8c45fSAndroid Build Coastguard Worker mDispatcherIsAlive.notify_all();
1011*38e8c45fSAndroid Build Coastguard Worker
1012*38e8c45fSAndroid Build Coastguard Worker // Run a dispatch loop if there are no pending commands.
1013*38e8c45fSAndroid Build Coastguard Worker // The dispatch loop might enqueue commands to run afterwards.
1014*38e8c45fSAndroid Build Coastguard Worker if (!haveCommandsLocked()) {
1015*38e8c45fSAndroid Build Coastguard Worker dispatchOnceInnerLocked(/*byref*/ nextWakeupTime);
1016*38e8c45fSAndroid Build Coastguard Worker }
1017*38e8c45fSAndroid Build Coastguard Worker
1018*38e8c45fSAndroid Build Coastguard Worker // Run all pending commands if there are any.
1019*38e8c45fSAndroid Build Coastguard Worker // If any commands were run then force the next poll to wake up immediately.
1020*38e8c45fSAndroid Build Coastguard Worker if (runCommandsLockedInterruptable()) {
1021*38e8c45fSAndroid Build Coastguard Worker nextWakeupTime = LLONG_MIN;
1022*38e8c45fSAndroid Build Coastguard Worker }
1023*38e8c45fSAndroid Build Coastguard Worker
1024*38e8c45fSAndroid Build Coastguard Worker // If we are still waiting for ack on some events,
1025*38e8c45fSAndroid Build Coastguard Worker // we might have to wake up earlier to check if an app is anr'ing.
1026*38e8c45fSAndroid Build Coastguard Worker const nsecs_t nextAnrCheck = processAnrsLocked();
1027*38e8c45fSAndroid Build Coastguard Worker nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);
1028*38e8c45fSAndroid Build Coastguard Worker
1029*38e8c45fSAndroid Build Coastguard Worker if (mPerDeviceInputLatencyMetricsFlag) {
1030*38e8c45fSAndroid Build Coastguard Worker processLatencyStatisticsLocked();
1031*38e8c45fSAndroid Build Coastguard Worker }
1032*38e8c45fSAndroid Build Coastguard Worker
1033*38e8c45fSAndroid Build Coastguard Worker // We are about to enter an infinitely long sleep, because we have no commands or
1034*38e8c45fSAndroid Build Coastguard Worker // pending or queued events
1035*38e8c45fSAndroid Build Coastguard Worker if (nextWakeupTime == LLONG_MAX) {
1036*38e8c45fSAndroid Build Coastguard Worker mDispatcherEnteredIdle.notify_all();
1037*38e8c45fSAndroid Build Coastguard Worker }
1038*38e8c45fSAndroid Build Coastguard Worker } // release lock
1039*38e8c45fSAndroid Build Coastguard Worker
1040*38e8c45fSAndroid Build Coastguard Worker // Wait for callback or timeout or wake. (make sure we round up, not down)
1041*38e8c45fSAndroid Build Coastguard Worker nsecs_t currentTime = now();
1042*38e8c45fSAndroid Build Coastguard Worker int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
1043*38e8c45fSAndroid Build Coastguard Worker mLooper->pollOnce(timeoutMillis);
1044*38e8c45fSAndroid Build Coastguard Worker }
1045*38e8c45fSAndroid Build Coastguard Worker
1046*38e8c45fSAndroid Build Coastguard Worker /**
1047*38e8c45fSAndroid Build Coastguard Worker * Raise ANR if there is no focused window.
1048*38e8c45fSAndroid Build Coastguard Worker * Before the ANR is raised, do a final state check:
1049*38e8c45fSAndroid Build Coastguard Worker * 1. The currently focused application must be the same one we are waiting for.
1050*38e8c45fSAndroid Build Coastguard Worker * 2. Ensure we still don't have a focused window.
1051*38e8c45fSAndroid Build Coastguard Worker */
processNoFocusedWindowAnrLocked()1052*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::processNoFocusedWindowAnrLocked() {
1053*38e8c45fSAndroid Build Coastguard Worker // Check if the application that we are waiting for is still focused.
1054*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<InputApplicationHandle> focusedApplication =
1055*38e8c45fSAndroid Build Coastguard Worker getValueByKey(mFocusedApplicationHandlesByDisplay, mAwaitedApplicationDisplayId);
1056*38e8c45fSAndroid Build Coastguard Worker if (focusedApplication == nullptr ||
1057*38e8c45fSAndroid Build Coastguard Worker focusedApplication->getApplicationToken() !=
1058*38e8c45fSAndroid Build Coastguard Worker mAwaitedFocusedApplication->getApplicationToken()) {
1059*38e8c45fSAndroid Build Coastguard Worker // Unexpected because we should have reset the ANR timer when focused application changed
1060*38e8c45fSAndroid Build Coastguard Worker ALOGE("Waited for a focused window, but focused application has already changed to %s",
1061*38e8c45fSAndroid Build Coastguard Worker focusedApplication->getName().c_str());
1062*38e8c45fSAndroid Build Coastguard Worker return; // The focused application has changed.
1063*38e8c45fSAndroid Build Coastguard Worker }
1064*38e8c45fSAndroid Build Coastguard Worker
1065*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle>& focusedWindowHandle =
1066*38e8c45fSAndroid Build Coastguard Worker getFocusedWindowHandleLocked(mAwaitedApplicationDisplayId);
1067*38e8c45fSAndroid Build Coastguard Worker if (focusedWindowHandle != nullptr) {
1068*38e8c45fSAndroid Build Coastguard Worker return; // We now have a focused window. No need for ANR.
1069*38e8c45fSAndroid Build Coastguard Worker }
1070*38e8c45fSAndroid Build Coastguard Worker onAnrLocked(mAwaitedFocusedApplication);
1071*38e8c45fSAndroid Build Coastguard Worker }
1072*38e8c45fSAndroid Build Coastguard Worker
1073*38e8c45fSAndroid Build Coastguard Worker /**
1074*38e8c45fSAndroid Build Coastguard Worker * Check if any of the connections' wait queues have events that are too old.
1075*38e8c45fSAndroid Build Coastguard Worker * If we waited for events to be ack'ed for more than the window timeout, raise an ANR.
1076*38e8c45fSAndroid Build Coastguard Worker * Return the time at which we should wake up next.
1077*38e8c45fSAndroid Build Coastguard Worker */
processAnrsLocked()1078*38e8c45fSAndroid Build Coastguard Worker nsecs_t InputDispatcher::processAnrsLocked() {
1079*38e8c45fSAndroid Build Coastguard Worker const nsecs_t currentTime = now();
1080*38e8c45fSAndroid Build Coastguard Worker nsecs_t nextAnrCheck = LLONG_MAX;
1081*38e8c45fSAndroid Build Coastguard Worker // Check if we are waiting for a focused window to appear. Raise ANR if waited too long
1082*38e8c45fSAndroid Build Coastguard Worker if (mNoFocusedWindowTimeoutTime.has_value() && mAwaitedFocusedApplication != nullptr) {
1083*38e8c45fSAndroid Build Coastguard Worker if (currentTime >= *mNoFocusedWindowTimeoutTime) {
1084*38e8c45fSAndroid Build Coastguard Worker processNoFocusedWindowAnrLocked();
1085*38e8c45fSAndroid Build Coastguard Worker mAwaitedFocusedApplication.reset();
1086*38e8c45fSAndroid Build Coastguard Worker mNoFocusedWindowTimeoutTime = std::nullopt;
1087*38e8c45fSAndroid Build Coastguard Worker return LLONG_MIN;
1088*38e8c45fSAndroid Build Coastguard Worker } else {
1089*38e8c45fSAndroid Build Coastguard Worker // Keep waiting. We will drop the event when mNoFocusedWindowTimeoutTime comes.
1090*38e8c45fSAndroid Build Coastguard Worker nextAnrCheck = *mNoFocusedWindowTimeoutTime;
1091*38e8c45fSAndroid Build Coastguard Worker }
1092*38e8c45fSAndroid Build Coastguard Worker }
1093*38e8c45fSAndroid Build Coastguard Worker
1094*38e8c45fSAndroid Build Coastguard Worker // Check if any connection ANRs are due
1095*38e8c45fSAndroid Build Coastguard Worker nextAnrCheck = std::min(nextAnrCheck, mAnrTracker.firstTimeout());
1096*38e8c45fSAndroid Build Coastguard Worker if (currentTime < nextAnrCheck) { // most likely scenario
1097*38e8c45fSAndroid Build Coastguard Worker return nextAnrCheck; // everything is normal. Let's check again at nextAnrCheck
1098*38e8c45fSAndroid Build Coastguard Worker }
1099*38e8c45fSAndroid Build Coastguard Worker
1100*38e8c45fSAndroid Build Coastguard Worker // If we reached here, we have an unresponsive connection.
1101*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<Connection> connection = getConnectionLocked(mAnrTracker.firstToken());
1102*38e8c45fSAndroid Build Coastguard Worker if (connection == nullptr) {
1103*38e8c45fSAndroid Build Coastguard Worker ALOGE("Could not find connection for entry %" PRId64, mAnrTracker.firstTimeout());
1104*38e8c45fSAndroid Build Coastguard Worker return nextAnrCheck;
1105*38e8c45fSAndroid Build Coastguard Worker }
1106*38e8c45fSAndroid Build Coastguard Worker connection->responsive = false;
1107*38e8c45fSAndroid Build Coastguard Worker // Stop waking up for this unresponsive connection
1108*38e8c45fSAndroid Build Coastguard Worker mAnrTracker.eraseToken(connection->getToken());
1109*38e8c45fSAndroid Build Coastguard Worker onAnrLocked(connection);
1110*38e8c45fSAndroid Build Coastguard Worker return LLONG_MIN;
1111*38e8c45fSAndroid Build Coastguard Worker }
1112*38e8c45fSAndroid Build Coastguard Worker
1113*38e8c45fSAndroid Build Coastguard Worker /**
1114*38e8c45fSAndroid Build Coastguard Worker * Check if enough time has passed since the last latency statistics push.
1115*38e8c45fSAndroid Build Coastguard Worker */
processLatencyStatisticsLocked()1116*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::processLatencyStatisticsLocked() {
1117*38e8c45fSAndroid Build Coastguard Worker const nsecs_t currentTime = now();
1118*38e8c45fSAndroid Build Coastguard Worker // Log the atom recording latency statistics if more than 6 hours passed from the last
1119*38e8c45fSAndroid Build Coastguard Worker // push
1120*38e8c45fSAndroid Build Coastguard Worker if (currentTime - mLastStatisticPushTime >= LATENCY_STATISTICS_PUSH_INTERVAL) {
1121*38e8c45fSAndroid Build Coastguard Worker mInputEventTimelineProcessor->pushLatencyStatistics();
1122*38e8c45fSAndroid Build Coastguard Worker mLastStatisticPushTime = currentTime;
1123*38e8c45fSAndroid Build Coastguard Worker }
1124*38e8c45fSAndroid Build Coastguard Worker }
1125*38e8c45fSAndroid Build Coastguard Worker
getDispatchingTimeoutLocked(const std::shared_ptr<Connection> & connection)1126*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds InputDispatcher::getDispatchingTimeoutLocked(
1127*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<Connection>& connection) {
1128*38e8c45fSAndroid Build Coastguard Worker if (connection->monitor) {
1129*38e8c45fSAndroid Build Coastguard Worker return mMonitorDispatchingTimeout;
1130*38e8c45fSAndroid Build Coastguard Worker }
1131*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle> window = getWindowHandleLocked(connection->getToken());
1132*38e8c45fSAndroid Build Coastguard Worker if (window != nullptr) {
1133*38e8c45fSAndroid Build Coastguard Worker return window->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
1134*38e8c45fSAndroid Build Coastguard Worker }
1135*38e8c45fSAndroid Build Coastguard Worker return DEFAULT_INPUT_DISPATCHING_TIMEOUT;
1136*38e8c45fSAndroid Build Coastguard Worker }
1137*38e8c45fSAndroid Build Coastguard Worker
dispatchOnceInnerLocked(nsecs_t & nextWakeupTime)1138*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::dispatchOnceInnerLocked(nsecs_t& nextWakeupTime) {
1139*38e8c45fSAndroid Build Coastguard Worker nsecs_t currentTime = now();
1140*38e8c45fSAndroid Build Coastguard Worker
1141*38e8c45fSAndroid Build Coastguard Worker // Reset the key repeat timer whenever normal dispatch is suspended while the
1142*38e8c45fSAndroid Build Coastguard Worker // device is in a non-interactive state. This is to ensure that we abort a key
1143*38e8c45fSAndroid Build Coastguard Worker // repeat if the device is just coming out of sleep.
1144*38e8c45fSAndroid Build Coastguard Worker if (!mDispatchEnabled) {
1145*38e8c45fSAndroid Build Coastguard Worker resetKeyRepeatLocked();
1146*38e8c45fSAndroid Build Coastguard Worker }
1147*38e8c45fSAndroid Build Coastguard Worker
1148*38e8c45fSAndroid Build Coastguard Worker // If dispatching is frozen, do not process timeouts or try to deliver any new events.
1149*38e8c45fSAndroid Build Coastguard Worker if (mDispatchFrozen) {
1150*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_FOCUS) {
1151*38e8c45fSAndroid Build Coastguard Worker ALOGD("Dispatch frozen. Waiting some more.");
1152*38e8c45fSAndroid Build Coastguard Worker }
1153*38e8c45fSAndroid Build Coastguard Worker return;
1154*38e8c45fSAndroid Build Coastguard Worker }
1155*38e8c45fSAndroid Build Coastguard Worker
1156*38e8c45fSAndroid Build Coastguard Worker // Ready to start a new event.
1157*38e8c45fSAndroid Build Coastguard Worker // If we don't already have a pending event, go grab one.
1158*38e8c45fSAndroid Build Coastguard Worker if (!mPendingEvent) {
1159*38e8c45fSAndroid Build Coastguard Worker if (mInboundQueue.empty()) {
1160*38e8c45fSAndroid Build Coastguard Worker // Synthesize a key repeat if appropriate.
1161*38e8c45fSAndroid Build Coastguard Worker if (mKeyRepeatState.lastKeyEntry) {
1162*38e8c45fSAndroid Build Coastguard Worker if (currentTime >= mKeyRepeatState.nextRepeatTime) {
1163*38e8c45fSAndroid Build Coastguard Worker mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
1164*38e8c45fSAndroid Build Coastguard Worker } else {
1165*38e8c45fSAndroid Build Coastguard Worker nextWakeupTime = std::min(nextWakeupTime, mKeyRepeatState.nextRepeatTime);
1166*38e8c45fSAndroid Build Coastguard Worker }
1167*38e8c45fSAndroid Build Coastguard Worker }
1168*38e8c45fSAndroid Build Coastguard Worker
1169*38e8c45fSAndroid Build Coastguard Worker // Nothing to do if there is no pending event.
1170*38e8c45fSAndroid Build Coastguard Worker if (!mPendingEvent) {
1171*38e8c45fSAndroid Build Coastguard Worker return;
1172*38e8c45fSAndroid Build Coastguard Worker }
1173*38e8c45fSAndroid Build Coastguard Worker } else {
1174*38e8c45fSAndroid Build Coastguard Worker // Inbound queue has at least one entry.
1175*38e8c45fSAndroid Build Coastguard Worker mPendingEvent = mInboundQueue.front();
1176*38e8c45fSAndroid Build Coastguard Worker mInboundQueue.pop_front();
1177*38e8c45fSAndroid Build Coastguard Worker traceInboundQueueLengthLocked();
1178*38e8c45fSAndroid Build Coastguard Worker }
1179*38e8c45fSAndroid Build Coastguard Worker
1180*38e8c45fSAndroid Build Coastguard Worker // Poke user activity for this event.
1181*38e8c45fSAndroid Build Coastguard Worker if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
1182*38e8c45fSAndroid Build Coastguard Worker pokeUserActivityLocked(*mPendingEvent);
1183*38e8c45fSAndroid Build Coastguard Worker }
1184*38e8c45fSAndroid Build Coastguard Worker }
1185*38e8c45fSAndroid Build Coastguard Worker
1186*38e8c45fSAndroid Build Coastguard Worker // Now we have an event to dispatch.
1187*38e8c45fSAndroid Build Coastguard Worker // All events are eventually dequeued and processed this way, even if we intend to drop them.
1188*38e8c45fSAndroid Build Coastguard Worker ALOG_ASSERT(mPendingEvent != nullptr);
1189*38e8c45fSAndroid Build Coastguard Worker bool done = false;
1190*38e8c45fSAndroid Build Coastguard Worker DropReason dropReason = DropReason::NOT_DROPPED;
1191*38e8c45fSAndroid Build Coastguard Worker if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
1192*38e8c45fSAndroid Build Coastguard Worker dropReason = DropReason::POLICY;
1193*38e8c45fSAndroid Build Coastguard Worker } else if (!mDispatchEnabled) {
1194*38e8c45fSAndroid Build Coastguard Worker dropReason = DropReason::DISABLED;
1195*38e8c45fSAndroid Build Coastguard Worker }
1196*38e8c45fSAndroid Build Coastguard Worker
1197*38e8c45fSAndroid Build Coastguard Worker if (mNextUnblockedEvent == mPendingEvent) {
1198*38e8c45fSAndroid Build Coastguard Worker mNextUnblockedEvent = nullptr;
1199*38e8c45fSAndroid Build Coastguard Worker }
1200*38e8c45fSAndroid Build Coastguard Worker
1201*38e8c45fSAndroid Build Coastguard Worker switch (mPendingEvent->type) {
1202*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::DEVICE_RESET: {
1203*38e8c45fSAndroid Build Coastguard Worker const DeviceResetEntry& typedEntry =
1204*38e8c45fSAndroid Build Coastguard Worker static_cast<const DeviceResetEntry&>(*mPendingEvent);
1205*38e8c45fSAndroid Build Coastguard Worker done = dispatchDeviceResetLocked(currentTime, typedEntry);
1206*38e8c45fSAndroid Build Coastguard Worker dropReason = DropReason::NOT_DROPPED; // device resets are never dropped
1207*38e8c45fSAndroid Build Coastguard Worker break;
1208*38e8c45fSAndroid Build Coastguard Worker }
1209*38e8c45fSAndroid Build Coastguard Worker
1210*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::FOCUS: {
1211*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const FocusEntry> typedEntry =
1212*38e8c45fSAndroid Build Coastguard Worker std::static_pointer_cast<const FocusEntry>(mPendingEvent);
1213*38e8c45fSAndroid Build Coastguard Worker dispatchFocusLocked(currentTime, typedEntry);
1214*38e8c45fSAndroid Build Coastguard Worker done = true;
1215*38e8c45fSAndroid Build Coastguard Worker dropReason = DropReason::NOT_DROPPED; // focus events are never dropped
1216*38e8c45fSAndroid Build Coastguard Worker break;
1217*38e8c45fSAndroid Build Coastguard Worker }
1218*38e8c45fSAndroid Build Coastguard Worker
1219*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::TOUCH_MODE_CHANGED: {
1220*38e8c45fSAndroid Build Coastguard Worker const auto typedEntry = std::static_pointer_cast<const TouchModeEntry>(mPendingEvent);
1221*38e8c45fSAndroid Build Coastguard Worker dispatchTouchModeChangeLocked(currentTime, typedEntry);
1222*38e8c45fSAndroid Build Coastguard Worker done = true;
1223*38e8c45fSAndroid Build Coastguard Worker dropReason = DropReason::NOT_DROPPED; // touch mode events are never dropped
1224*38e8c45fSAndroid Build Coastguard Worker break;
1225*38e8c45fSAndroid Build Coastguard Worker }
1226*38e8c45fSAndroid Build Coastguard Worker
1227*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::POINTER_CAPTURE_CHANGED: {
1228*38e8c45fSAndroid Build Coastguard Worker const auto typedEntry =
1229*38e8c45fSAndroid Build Coastguard Worker std::static_pointer_cast<const PointerCaptureChangedEntry>(mPendingEvent);
1230*38e8c45fSAndroid Build Coastguard Worker dispatchPointerCaptureChangedLocked(currentTime, typedEntry, dropReason);
1231*38e8c45fSAndroid Build Coastguard Worker done = true;
1232*38e8c45fSAndroid Build Coastguard Worker break;
1233*38e8c45fSAndroid Build Coastguard Worker }
1234*38e8c45fSAndroid Build Coastguard Worker
1235*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::DRAG: {
1236*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const DragEntry> typedEntry =
1237*38e8c45fSAndroid Build Coastguard Worker std::static_pointer_cast<const DragEntry>(mPendingEvent);
1238*38e8c45fSAndroid Build Coastguard Worker dispatchDragLocked(currentTime, typedEntry);
1239*38e8c45fSAndroid Build Coastguard Worker done = true;
1240*38e8c45fSAndroid Build Coastguard Worker break;
1241*38e8c45fSAndroid Build Coastguard Worker }
1242*38e8c45fSAndroid Build Coastguard Worker
1243*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::KEY: {
1244*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const KeyEntry> keyEntry =
1245*38e8c45fSAndroid Build Coastguard Worker std::static_pointer_cast<const KeyEntry>(mPendingEvent);
1246*38e8c45fSAndroid Build Coastguard Worker if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *keyEntry)) {
1247*38e8c45fSAndroid Build Coastguard Worker dropReason = DropReason::STALE;
1248*38e8c45fSAndroid Build Coastguard Worker }
1249*38e8c45fSAndroid Build Coastguard Worker if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
1250*38e8c45fSAndroid Build Coastguard Worker dropReason = DropReason::BLOCKED;
1251*38e8c45fSAndroid Build Coastguard Worker }
1252*38e8c45fSAndroid Build Coastguard Worker done = dispatchKeyLocked(currentTime, keyEntry, &dropReason, nextWakeupTime);
1253*38e8c45fSAndroid Build Coastguard Worker break;
1254*38e8c45fSAndroid Build Coastguard Worker }
1255*38e8c45fSAndroid Build Coastguard Worker
1256*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::MOTION: {
1257*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const MotionEntry> motionEntry =
1258*38e8c45fSAndroid Build Coastguard Worker std::static_pointer_cast<const MotionEntry>(mPendingEvent);
1259*38e8c45fSAndroid Build Coastguard Worker if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *motionEntry)) {
1260*38e8c45fSAndroid Build Coastguard Worker // The event is stale. However, only drop stale events if there isn't an ongoing
1261*38e8c45fSAndroid Build Coastguard Worker // gesture. That would allow us to complete the processing of the current stroke.
1262*38e8c45fSAndroid Build Coastguard Worker const auto touchStateIt = mTouchStatesByDisplay.find(motionEntry->displayId);
1263*38e8c45fSAndroid Build Coastguard Worker if (touchStateIt != mTouchStatesByDisplay.end()) {
1264*38e8c45fSAndroid Build Coastguard Worker const TouchState& touchState = touchStateIt->second;
1265*38e8c45fSAndroid Build Coastguard Worker if (!touchState.hasTouchingPointers(motionEntry->deviceId) &&
1266*38e8c45fSAndroid Build Coastguard Worker !touchState.hasHoveringPointers(motionEntry->deviceId)) {
1267*38e8c45fSAndroid Build Coastguard Worker dropReason = DropReason::STALE;
1268*38e8c45fSAndroid Build Coastguard Worker }
1269*38e8c45fSAndroid Build Coastguard Worker }
1270*38e8c45fSAndroid Build Coastguard Worker }
1271*38e8c45fSAndroid Build Coastguard Worker if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
1272*38e8c45fSAndroid Build Coastguard Worker if (!isFromSource(motionEntry->source, AINPUT_SOURCE_CLASS_POINTER)) {
1273*38e8c45fSAndroid Build Coastguard Worker // Only drop events that are focus-dispatched.
1274*38e8c45fSAndroid Build Coastguard Worker dropReason = DropReason::BLOCKED;
1275*38e8c45fSAndroid Build Coastguard Worker }
1276*38e8c45fSAndroid Build Coastguard Worker }
1277*38e8c45fSAndroid Build Coastguard Worker done = dispatchMotionLocked(currentTime, motionEntry, &dropReason, nextWakeupTime);
1278*38e8c45fSAndroid Build Coastguard Worker break;
1279*38e8c45fSAndroid Build Coastguard Worker }
1280*38e8c45fSAndroid Build Coastguard Worker
1281*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::SENSOR: {
1282*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const SensorEntry> sensorEntry =
1283*38e8c45fSAndroid Build Coastguard Worker std::static_pointer_cast<const SensorEntry>(mPendingEvent);
1284*38e8c45fSAndroid Build Coastguard Worker
1285*38e8c45fSAndroid Build Coastguard Worker // Sensor timestamps use SYSTEM_TIME_BOOTTIME time base, so we can't use
1286*38e8c45fSAndroid Build Coastguard Worker // 'currentTime' here, get SYSTEM_TIME_BOOTTIME instead.
1287*38e8c45fSAndroid Build Coastguard Worker nsecs_t bootTime = systemTime(SYSTEM_TIME_BOOTTIME);
1288*38e8c45fSAndroid Build Coastguard Worker if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(bootTime, *sensorEntry)) {
1289*38e8c45fSAndroid Build Coastguard Worker dropReason = DropReason::STALE;
1290*38e8c45fSAndroid Build Coastguard Worker }
1291*38e8c45fSAndroid Build Coastguard Worker dispatchSensorLocked(currentTime, sensorEntry, &dropReason, nextWakeupTime);
1292*38e8c45fSAndroid Build Coastguard Worker done = true;
1293*38e8c45fSAndroid Build Coastguard Worker break;
1294*38e8c45fSAndroid Build Coastguard Worker }
1295*38e8c45fSAndroid Build Coastguard Worker }
1296*38e8c45fSAndroid Build Coastguard Worker
1297*38e8c45fSAndroid Build Coastguard Worker if (done) {
1298*38e8c45fSAndroid Build Coastguard Worker if (dropReason != DropReason::NOT_DROPPED) {
1299*38e8c45fSAndroid Build Coastguard Worker dropInboundEventLocked(*mPendingEvent, dropReason);
1300*38e8c45fSAndroid Build Coastguard Worker }
1301*38e8c45fSAndroid Build Coastguard Worker mLastDropReason = dropReason;
1302*38e8c45fSAndroid Build Coastguard Worker
1303*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
1304*38e8c45fSAndroid Build Coastguard Worker if (auto& traceTracker = getTraceTracker(*mPendingEvent); traceTracker != nullptr) {
1305*38e8c45fSAndroid Build Coastguard Worker mTracer->eventProcessingComplete(*traceTracker, currentTime);
1306*38e8c45fSAndroid Build Coastguard Worker }
1307*38e8c45fSAndroid Build Coastguard Worker }
1308*38e8c45fSAndroid Build Coastguard Worker
1309*38e8c45fSAndroid Build Coastguard Worker releasePendingEventLocked();
1310*38e8c45fSAndroid Build Coastguard Worker nextWakeupTime = LLONG_MIN; // force next poll to wake up immediately
1311*38e8c45fSAndroid Build Coastguard Worker }
1312*38e8c45fSAndroid Build Coastguard Worker }
1313*38e8c45fSAndroid Build Coastguard Worker
isStaleEvent(nsecs_t currentTime,const EventEntry & entry)1314*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::isStaleEvent(nsecs_t currentTime, const EventEntry& entry) {
1315*38e8c45fSAndroid Build Coastguard Worker return mPolicy.isStaleEvent(currentTime, entry.eventTime);
1316*38e8c45fSAndroid Build Coastguard Worker }
1317*38e8c45fSAndroid Build Coastguard Worker
1318*38e8c45fSAndroid Build Coastguard Worker /**
1319*38e8c45fSAndroid Build Coastguard Worker * Return true if the events preceding this incoming motion event should be dropped
1320*38e8c45fSAndroid Build Coastguard Worker * Return false otherwise (the default behaviour)
1321*38e8c45fSAndroid Build Coastguard Worker */
shouldPruneInboundQueueLocked(const MotionEntry & motionEntry) const1322*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::shouldPruneInboundQueueLocked(const MotionEntry& motionEntry) const {
1323*38e8c45fSAndroid Build Coastguard Worker const bool isPointerDownEvent = motionEntry.action == AMOTION_EVENT_ACTION_DOWN &&
1324*38e8c45fSAndroid Build Coastguard Worker isFromSource(motionEntry.source, AINPUT_SOURCE_CLASS_POINTER);
1325*38e8c45fSAndroid Build Coastguard Worker
1326*38e8c45fSAndroid Build Coastguard Worker // Optimize case where the current application is unresponsive and the user
1327*38e8c45fSAndroid Build Coastguard Worker // decides to touch a window in a different application.
1328*38e8c45fSAndroid Build Coastguard Worker // If the application takes too long to catch up then we drop all events preceding
1329*38e8c45fSAndroid Build Coastguard Worker // the touch into the other window.
1330*38e8c45fSAndroid Build Coastguard Worker if (isPointerDownEvent && mAwaitedFocusedApplication != nullptr) {
1331*38e8c45fSAndroid Build Coastguard Worker const ui::LogicalDisplayId displayId = motionEntry.displayId;
1332*38e8c45fSAndroid Build Coastguard Worker const auto [x, y] = resolveTouchedPosition(motionEntry);
1333*38e8c45fSAndroid Build Coastguard Worker const bool isStylus = isPointerFromStylus(motionEntry, /*pointerIndex=*/0);
1334*38e8c45fSAndroid Build Coastguard Worker
1335*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> touchedWindowHandle =
1336*38e8c45fSAndroid Build Coastguard Worker findTouchedWindowAtLocked(displayId, x, y, isStylus);
1337*38e8c45fSAndroid Build Coastguard Worker if (touchedWindowHandle != nullptr &&
1338*38e8c45fSAndroid Build Coastguard Worker touchedWindowHandle->getApplicationToken() !=
1339*38e8c45fSAndroid Build Coastguard Worker mAwaitedFocusedApplication->getApplicationToken()) {
1340*38e8c45fSAndroid Build Coastguard Worker // User touched a different application than the one we are waiting on.
1341*38e8c45fSAndroid Build Coastguard Worker ALOGI("Pruning input queue because user touched a different application while waiting "
1342*38e8c45fSAndroid Build Coastguard Worker "for %s",
1343*38e8c45fSAndroid Build Coastguard Worker mAwaitedFocusedApplication->getName().c_str());
1344*38e8c45fSAndroid Build Coastguard Worker return true;
1345*38e8c45fSAndroid Build Coastguard Worker }
1346*38e8c45fSAndroid Build Coastguard Worker
1347*38e8c45fSAndroid Build Coastguard Worker // Alternatively, maybe there's a spy window that could handle this event.
1348*38e8c45fSAndroid Build Coastguard Worker const std::vector<sp<WindowInfoHandle>> touchedSpies =
1349*38e8c45fSAndroid Build Coastguard Worker findTouchedSpyWindowsAtLocked(displayId, x, y, isStylus, motionEntry.deviceId);
1350*38e8c45fSAndroid Build Coastguard Worker for (const auto& windowHandle : touchedSpies) {
1351*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<Connection> connection =
1352*38e8c45fSAndroid Build Coastguard Worker getConnectionLocked(windowHandle->getToken());
1353*38e8c45fSAndroid Build Coastguard Worker if (connection != nullptr && connection->responsive) {
1354*38e8c45fSAndroid Build Coastguard Worker // This spy window could take more input. Drop all events preceding this
1355*38e8c45fSAndroid Build Coastguard Worker // event, so that the spy window can get a chance to receive the stream.
1356*38e8c45fSAndroid Build Coastguard Worker ALOGW("Pruning the input queue because %s is unresponsive, but we have a "
1357*38e8c45fSAndroid Build Coastguard Worker "responsive spy window that may handle the event.",
1358*38e8c45fSAndroid Build Coastguard Worker mAwaitedFocusedApplication->getName().c_str());
1359*38e8c45fSAndroid Build Coastguard Worker return true;
1360*38e8c45fSAndroid Build Coastguard Worker }
1361*38e8c45fSAndroid Build Coastguard Worker }
1362*38e8c45fSAndroid Build Coastguard Worker }
1363*38e8c45fSAndroid Build Coastguard Worker
1364*38e8c45fSAndroid Build Coastguard Worker return false;
1365*38e8c45fSAndroid Build Coastguard Worker }
1366*38e8c45fSAndroid Build Coastguard Worker
enqueueInboundEventLocked(std::unique_ptr<EventEntry> newEntry)1367*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::enqueueInboundEventLocked(std::unique_ptr<EventEntry> newEntry) {
1368*38e8c45fSAndroid Build Coastguard Worker bool needWake = mInboundQueue.empty();
1369*38e8c45fSAndroid Build Coastguard Worker mInboundQueue.push_back(std::move(newEntry));
1370*38e8c45fSAndroid Build Coastguard Worker const EventEntry& entry = *(mInboundQueue.back());
1371*38e8c45fSAndroid Build Coastguard Worker traceInboundQueueLengthLocked();
1372*38e8c45fSAndroid Build Coastguard Worker
1373*38e8c45fSAndroid Build Coastguard Worker switch (entry.type) {
1374*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::KEY: {
1375*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF((entry.policyFlags & POLICY_FLAG_TRUSTED) == 0,
1376*38e8c45fSAndroid Build Coastguard Worker "Unexpected untrusted event.");
1377*38e8c45fSAndroid Build Coastguard Worker
1378*38e8c45fSAndroid Build Coastguard Worker const KeyEntry& keyEntry = static_cast<const KeyEntry&>(entry);
1379*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
1380*38e8c45fSAndroid Build Coastguard Worker ensureEventTraced(keyEntry);
1381*38e8c45fSAndroid Build Coastguard Worker }
1382*38e8c45fSAndroid Build Coastguard Worker
1383*38e8c45fSAndroid Build Coastguard Worker // If a new up event comes in, and the pending event with same key code has been asked
1384*38e8c45fSAndroid Build Coastguard Worker // to try again later because of the policy. We have to reset the intercept key wake up
1385*38e8c45fSAndroid Build Coastguard Worker // time for it may have been handled in the policy and could be dropped.
1386*38e8c45fSAndroid Build Coastguard Worker if (keyEntry.action == AKEY_EVENT_ACTION_UP && mPendingEvent &&
1387*38e8c45fSAndroid Build Coastguard Worker mPendingEvent->type == EventEntry::Type::KEY) {
1388*38e8c45fSAndroid Build Coastguard Worker const KeyEntry& pendingKey = static_cast<const KeyEntry&>(*mPendingEvent);
1389*38e8c45fSAndroid Build Coastguard Worker if (pendingKey.keyCode == keyEntry.keyCode &&
1390*38e8c45fSAndroid Build Coastguard Worker pendingKey.interceptKeyResult ==
1391*38e8c45fSAndroid Build Coastguard Worker KeyEntry::InterceptKeyResult::TRY_AGAIN_LATER) {
1392*38e8c45fSAndroid Build Coastguard Worker pendingKey.interceptKeyResult = KeyEntry::InterceptKeyResult::UNKNOWN;
1393*38e8c45fSAndroid Build Coastguard Worker pendingKey.interceptKeyWakeupTime = 0;
1394*38e8c45fSAndroid Build Coastguard Worker needWake = true;
1395*38e8c45fSAndroid Build Coastguard Worker }
1396*38e8c45fSAndroid Build Coastguard Worker }
1397*38e8c45fSAndroid Build Coastguard Worker break;
1398*38e8c45fSAndroid Build Coastguard Worker }
1399*38e8c45fSAndroid Build Coastguard Worker
1400*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::MOTION: {
1401*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF((entry.policyFlags & POLICY_FLAG_TRUSTED) == 0,
1402*38e8c45fSAndroid Build Coastguard Worker "Unexpected untrusted event.");
1403*38e8c45fSAndroid Build Coastguard Worker const auto& motionEntry = static_cast<const MotionEntry&>(entry);
1404*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
1405*38e8c45fSAndroid Build Coastguard Worker ensureEventTraced(motionEntry);
1406*38e8c45fSAndroid Build Coastguard Worker }
1407*38e8c45fSAndroid Build Coastguard Worker if (shouldPruneInboundQueueLocked(motionEntry)) {
1408*38e8c45fSAndroid Build Coastguard Worker mNextUnblockedEvent = mInboundQueue.back();
1409*38e8c45fSAndroid Build Coastguard Worker needWake = true;
1410*38e8c45fSAndroid Build Coastguard Worker }
1411*38e8c45fSAndroid Build Coastguard Worker
1412*38e8c45fSAndroid Build Coastguard Worker const bool isPointerDownEvent = motionEntry.action == AMOTION_EVENT_ACTION_DOWN &&
1413*38e8c45fSAndroid Build Coastguard Worker isFromSource(motionEntry.source, AINPUT_SOURCE_CLASS_POINTER);
1414*38e8c45fSAndroid Build Coastguard Worker if (isPointerDownEvent && mKeyIsWaitingForEventsTimeout) {
1415*38e8c45fSAndroid Build Coastguard Worker // Prevent waiting too long for unprocessed events: if we have a pending key event,
1416*38e8c45fSAndroid Build Coastguard Worker // and some other events have not yet been processed, the dispatcher will wait for
1417*38e8c45fSAndroid Build Coastguard Worker // these events to be processed before dispatching the key event. This is because
1418*38e8c45fSAndroid Build Coastguard Worker // the unprocessed events may cause the focus to change (for example, by launching a
1419*38e8c45fSAndroid Build Coastguard Worker // new window or tapping a different window). To prevent waiting too long, we force
1420*38e8c45fSAndroid Build Coastguard Worker // the key to be sent to the currently focused window when a new tap comes in.
1421*38e8c45fSAndroid Build Coastguard Worker ALOGD("Received a new pointer down event, stop waiting for events to process and "
1422*38e8c45fSAndroid Build Coastguard Worker "just send the pending key event to the currently focused window.");
1423*38e8c45fSAndroid Build Coastguard Worker mKeyIsWaitingForEventsTimeout = now();
1424*38e8c45fSAndroid Build Coastguard Worker needWake = true;
1425*38e8c45fSAndroid Build Coastguard Worker }
1426*38e8c45fSAndroid Build Coastguard Worker break;
1427*38e8c45fSAndroid Build Coastguard Worker }
1428*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::FOCUS: {
1429*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("Focus events should be inserted using enqueueFocusEventLocked");
1430*38e8c45fSAndroid Build Coastguard Worker break;
1431*38e8c45fSAndroid Build Coastguard Worker }
1432*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::TOUCH_MODE_CHANGED:
1433*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::DEVICE_RESET:
1434*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::SENSOR:
1435*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::POINTER_CAPTURE_CHANGED:
1436*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::DRAG: {
1437*38e8c45fSAndroid Build Coastguard Worker // nothing to do
1438*38e8c45fSAndroid Build Coastguard Worker break;
1439*38e8c45fSAndroid Build Coastguard Worker }
1440*38e8c45fSAndroid Build Coastguard Worker }
1441*38e8c45fSAndroid Build Coastguard Worker
1442*38e8c45fSAndroid Build Coastguard Worker return needWake;
1443*38e8c45fSAndroid Build Coastguard Worker }
1444*38e8c45fSAndroid Build Coastguard Worker
addRecentEventLocked(std::shared_ptr<const EventEntry> entry)1445*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::addRecentEventLocked(std::shared_ptr<const EventEntry> entry) {
1446*38e8c45fSAndroid Build Coastguard Worker // Do not store sensor event in recent queue to avoid flooding the queue.
1447*38e8c45fSAndroid Build Coastguard Worker if (entry->type != EventEntry::Type::SENSOR) {
1448*38e8c45fSAndroid Build Coastguard Worker mRecentQueue.push_back(entry);
1449*38e8c45fSAndroid Build Coastguard Worker }
1450*38e8c45fSAndroid Build Coastguard Worker if (mRecentQueue.size() > RECENT_QUEUE_MAX_SIZE) {
1451*38e8c45fSAndroid Build Coastguard Worker mRecentQueue.pop_front();
1452*38e8c45fSAndroid Build Coastguard Worker }
1453*38e8c45fSAndroid Build Coastguard Worker }
1454*38e8c45fSAndroid Build Coastguard Worker
findTouchedWindowAtLocked(ui::LogicalDisplayId displayId,float x,float y,bool isStylus,bool ignoreDragWindow) const1455*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> InputDispatcher::findTouchedWindowAtLocked(ui::LogicalDisplayId displayId,
1456*38e8c45fSAndroid Build Coastguard Worker float x, float y, bool isStylus,
1457*38e8c45fSAndroid Build Coastguard Worker bool ignoreDragWindow) const {
1458*38e8c45fSAndroid Build Coastguard Worker // Traverse windows from front to back to find touched window.
1459*38e8c45fSAndroid Build Coastguard Worker const auto& windowHandles = getWindowHandlesLocked(displayId);
1460*38e8c45fSAndroid Build Coastguard Worker for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {
1461*38e8c45fSAndroid Build Coastguard Worker if (ignoreDragWindow && haveSameToken(windowHandle, mDragState->dragWindow)) {
1462*38e8c45fSAndroid Build Coastguard Worker continue;
1463*38e8c45fSAndroid Build Coastguard Worker }
1464*38e8c45fSAndroid Build Coastguard Worker
1465*38e8c45fSAndroid Build Coastguard Worker const WindowInfo& info = *windowHandle->getInfo();
1466*38e8c45fSAndroid Build Coastguard Worker if (!info.isSpy() &&
1467*38e8c45fSAndroid Build Coastguard Worker windowAcceptsTouchAt(info, displayId, x, y, isStylus, getTransformLocked(displayId))) {
1468*38e8c45fSAndroid Build Coastguard Worker return windowHandle;
1469*38e8c45fSAndroid Build Coastguard Worker }
1470*38e8c45fSAndroid Build Coastguard Worker }
1471*38e8c45fSAndroid Build Coastguard Worker return nullptr;
1472*38e8c45fSAndroid Build Coastguard Worker }
1473*38e8c45fSAndroid Build Coastguard Worker
findOutsideTargetsLocked(ui::LogicalDisplayId displayId,const sp<WindowInfoHandle> & touchedWindow,int32_t pointerId) const1474*38e8c45fSAndroid Build Coastguard Worker std::vector<InputTarget> InputDispatcher::findOutsideTargetsLocked(
1475*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId displayId, const sp<WindowInfoHandle>& touchedWindow,
1476*38e8c45fSAndroid Build Coastguard Worker int32_t pointerId) const {
1477*38e8c45fSAndroid Build Coastguard Worker if (touchedWindow == nullptr) {
1478*38e8c45fSAndroid Build Coastguard Worker return {};
1479*38e8c45fSAndroid Build Coastguard Worker }
1480*38e8c45fSAndroid Build Coastguard Worker // Traverse windows from front to back until we encounter the touched window.
1481*38e8c45fSAndroid Build Coastguard Worker std::vector<InputTarget> outsideTargets;
1482*38e8c45fSAndroid Build Coastguard Worker const auto& windowHandles = getWindowHandlesLocked(displayId);
1483*38e8c45fSAndroid Build Coastguard Worker for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {
1484*38e8c45fSAndroid Build Coastguard Worker if (windowHandle == touchedWindow) {
1485*38e8c45fSAndroid Build Coastguard Worker // Stop iterating once we found a touched window. Any WATCH_OUTSIDE_TOUCH window
1486*38e8c45fSAndroid Build Coastguard Worker // below the touched window will not get ACTION_OUTSIDE event.
1487*38e8c45fSAndroid Build Coastguard Worker return outsideTargets;
1488*38e8c45fSAndroid Build Coastguard Worker }
1489*38e8c45fSAndroid Build Coastguard Worker
1490*38e8c45fSAndroid Build Coastguard Worker const WindowInfo& info = *windowHandle->getInfo();
1491*38e8c45fSAndroid Build Coastguard Worker if (info.inputConfig.test(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH)) {
1492*38e8c45fSAndroid Build Coastguard Worker std::bitset<MAX_POINTER_ID + 1> pointerIds;
1493*38e8c45fSAndroid Build Coastguard Worker pointerIds.set(pointerId);
1494*38e8c45fSAndroid Build Coastguard Worker addPointerWindowTargetLocked(windowHandle, InputTarget::DispatchMode::OUTSIDE,
1495*38e8c45fSAndroid Build Coastguard Worker ftl::Flags<InputTarget::Flags>(), pointerIds,
1496*38e8c45fSAndroid Build Coastguard Worker /*firstDownTimeInTarget=*/std::nullopt, outsideTargets);
1497*38e8c45fSAndroid Build Coastguard Worker }
1498*38e8c45fSAndroid Build Coastguard Worker }
1499*38e8c45fSAndroid Build Coastguard Worker return outsideTargets;
1500*38e8c45fSAndroid Build Coastguard Worker }
1501*38e8c45fSAndroid Build Coastguard Worker
findTouchedSpyWindowsAtLocked(ui::LogicalDisplayId displayId,float x,float y,bool isStylus,DeviceId deviceId) const1502*38e8c45fSAndroid Build Coastguard Worker std::vector<sp<WindowInfoHandle>> InputDispatcher::findTouchedSpyWindowsAtLocked(
1503*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId displayId, float x, float y, bool isStylus, DeviceId deviceId) const {
1504*38e8c45fSAndroid Build Coastguard Worker // Traverse windows from front to back and gather the touched spy windows.
1505*38e8c45fSAndroid Build Coastguard Worker std::vector<sp<WindowInfoHandle>> spyWindows;
1506*38e8c45fSAndroid Build Coastguard Worker const auto& windowHandles = getWindowHandlesLocked(displayId);
1507*38e8c45fSAndroid Build Coastguard Worker for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {
1508*38e8c45fSAndroid Build Coastguard Worker const WindowInfo& info = *windowHandle->getInfo();
1509*38e8c45fSAndroid Build Coastguard Worker if (!windowAcceptsTouchAt(info, displayId, x, y, isStylus, getTransformLocked(displayId))) {
1510*38e8c45fSAndroid Build Coastguard Worker // Generally, we would skip any pointer that's outside of the window. However, if the
1511*38e8c45fSAndroid Build Coastguard Worker // spy prevents splitting, and already has some of the pointers from this device, then
1512*38e8c45fSAndroid Build Coastguard Worker // it should get more pointers from the same device, even if they are outside of that
1513*38e8c45fSAndroid Build Coastguard Worker // window
1514*38e8c45fSAndroid Build Coastguard Worker if (info.supportsSplitTouch()) {
1515*38e8c45fSAndroid Build Coastguard Worker continue;
1516*38e8c45fSAndroid Build Coastguard Worker }
1517*38e8c45fSAndroid Build Coastguard Worker
1518*38e8c45fSAndroid Build Coastguard Worker // We know that split touch is not supported. Skip this window only if it doesn't have
1519*38e8c45fSAndroid Build Coastguard Worker // any touching pointers for this device already.
1520*38e8c45fSAndroid Build Coastguard Worker if (!windowHasTouchingPointersLocked(windowHandle, deviceId)) {
1521*38e8c45fSAndroid Build Coastguard Worker continue;
1522*38e8c45fSAndroid Build Coastguard Worker }
1523*38e8c45fSAndroid Build Coastguard Worker // If it already has pointers down for this device, then give it this pointer, too.
1524*38e8c45fSAndroid Build Coastguard Worker }
1525*38e8c45fSAndroid Build Coastguard Worker if (!info.isSpy()) {
1526*38e8c45fSAndroid Build Coastguard Worker // The first touched non-spy window was found, so return the spy windows touched so far.
1527*38e8c45fSAndroid Build Coastguard Worker return spyWindows;
1528*38e8c45fSAndroid Build Coastguard Worker }
1529*38e8c45fSAndroid Build Coastguard Worker spyWindows.push_back(windowHandle);
1530*38e8c45fSAndroid Build Coastguard Worker }
1531*38e8c45fSAndroid Build Coastguard Worker return spyWindows;
1532*38e8c45fSAndroid Build Coastguard Worker }
1533*38e8c45fSAndroid Build Coastguard Worker
dropInboundEventLocked(const EventEntry & entry,DropReason dropReason)1534*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::dropInboundEventLocked(const EventEntry& entry, DropReason dropReason) {
1535*38e8c45fSAndroid Build Coastguard Worker const char* reason;
1536*38e8c45fSAndroid Build Coastguard Worker switch (dropReason) {
1537*38e8c45fSAndroid Build Coastguard Worker case DropReason::POLICY:
1538*38e8c45fSAndroid Build Coastguard Worker if (debugInboundEventDetails()) {
1539*38e8c45fSAndroid Build Coastguard Worker ALOGD("Dropped event because policy consumed it.");
1540*38e8c45fSAndroid Build Coastguard Worker }
1541*38e8c45fSAndroid Build Coastguard Worker reason = "inbound event was dropped because the policy consumed it";
1542*38e8c45fSAndroid Build Coastguard Worker break;
1543*38e8c45fSAndroid Build Coastguard Worker case DropReason::DISABLED:
1544*38e8c45fSAndroid Build Coastguard Worker if (mLastDropReason != DropReason::DISABLED) {
1545*38e8c45fSAndroid Build Coastguard Worker ALOGI("Dropped event because input dispatch is disabled.");
1546*38e8c45fSAndroid Build Coastguard Worker }
1547*38e8c45fSAndroid Build Coastguard Worker reason = "inbound event was dropped because input dispatch is disabled";
1548*38e8c45fSAndroid Build Coastguard Worker break;
1549*38e8c45fSAndroid Build Coastguard Worker case DropReason::BLOCKED:
1550*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "Dropping because the current application is not responding and the user "
1551*38e8c45fSAndroid Build Coastguard Worker "has started interacting with a different application: "
1552*38e8c45fSAndroid Build Coastguard Worker << entry.getDescription();
1553*38e8c45fSAndroid Build Coastguard Worker reason = "inbound event was dropped because the current application is not responding "
1554*38e8c45fSAndroid Build Coastguard Worker "and the user has started interacting with a different application";
1555*38e8c45fSAndroid Build Coastguard Worker break;
1556*38e8c45fSAndroid Build Coastguard Worker case DropReason::STALE:
1557*38e8c45fSAndroid Build Coastguard Worker ALOGI("Dropped event because it is stale.");
1558*38e8c45fSAndroid Build Coastguard Worker reason = "inbound event was dropped because it is stale";
1559*38e8c45fSAndroid Build Coastguard Worker break;
1560*38e8c45fSAndroid Build Coastguard Worker case DropReason::NO_POINTER_CAPTURE:
1561*38e8c45fSAndroid Build Coastguard Worker ALOGI("Dropped event because there is no window with Pointer Capture.");
1562*38e8c45fSAndroid Build Coastguard Worker reason = "inbound event was dropped because there is no window with Pointer Capture";
1563*38e8c45fSAndroid Build Coastguard Worker break;
1564*38e8c45fSAndroid Build Coastguard Worker case DropReason::NOT_DROPPED: {
1565*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("Should not be dropping a NOT_DROPPED event");
1566*38e8c45fSAndroid Build Coastguard Worker return;
1567*38e8c45fSAndroid Build Coastguard Worker }
1568*38e8c45fSAndroid Build Coastguard Worker }
1569*38e8c45fSAndroid Build Coastguard Worker
1570*38e8c45fSAndroid Build Coastguard Worker switch (entry.type) {
1571*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::KEY: {
1572*38e8c45fSAndroid Build Coastguard Worker const KeyEntry& keyEntry = static_cast<const KeyEntry&>(entry);
1573*38e8c45fSAndroid Build Coastguard Worker CancelationOptions options(CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS, reason,
1574*38e8c45fSAndroid Build Coastguard Worker keyEntry.traceTracker);
1575*38e8c45fSAndroid Build Coastguard Worker options.displayId = keyEntry.displayId;
1576*38e8c45fSAndroid Build Coastguard Worker options.deviceId = keyEntry.deviceId;
1577*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForAllConnectionsLocked(options);
1578*38e8c45fSAndroid Build Coastguard Worker break;
1579*38e8c45fSAndroid Build Coastguard Worker }
1580*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::MOTION: {
1581*38e8c45fSAndroid Build Coastguard Worker const MotionEntry& motionEntry = static_cast<const MotionEntry&>(entry);
1582*38e8c45fSAndroid Build Coastguard Worker if (motionEntry.source & AINPUT_SOURCE_CLASS_POINTER) {
1583*38e8c45fSAndroid Build Coastguard Worker CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS, reason,
1584*38e8c45fSAndroid Build Coastguard Worker motionEntry.traceTracker);
1585*38e8c45fSAndroid Build Coastguard Worker options.displayId = motionEntry.displayId;
1586*38e8c45fSAndroid Build Coastguard Worker options.deviceId = motionEntry.deviceId;
1587*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForAllConnectionsLocked(options);
1588*38e8c45fSAndroid Build Coastguard Worker } else {
1589*38e8c45fSAndroid Build Coastguard Worker CancelationOptions options(CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS,
1590*38e8c45fSAndroid Build Coastguard Worker reason, motionEntry.traceTracker);
1591*38e8c45fSAndroid Build Coastguard Worker options.displayId = motionEntry.displayId;
1592*38e8c45fSAndroid Build Coastguard Worker options.deviceId = motionEntry.deviceId;
1593*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForAllConnectionsLocked(options);
1594*38e8c45fSAndroid Build Coastguard Worker }
1595*38e8c45fSAndroid Build Coastguard Worker break;
1596*38e8c45fSAndroid Build Coastguard Worker }
1597*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::SENSOR: {
1598*38e8c45fSAndroid Build Coastguard Worker break;
1599*38e8c45fSAndroid Build Coastguard Worker }
1600*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::POINTER_CAPTURE_CHANGED:
1601*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::DRAG: {
1602*38e8c45fSAndroid Build Coastguard Worker break;
1603*38e8c45fSAndroid Build Coastguard Worker }
1604*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::FOCUS:
1605*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::TOUCH_MODE_CHANGED:
1606*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::DEVICE_RESET: {
1607*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("Should not drop %s events", ftl::enum_string(entry.type).c_str());
1608*38e8c45fSAndroid Build Coastguard Worker break;
1609*38e8c45fSAndroid Build Coastguard Worker }
1610*38e8c45fSAndroid Build Coastguard Worker }
1611*38e8c45fSAndroid Build Coastguard Worker }
1612*38e8c45fSAndroid Build Coastguard Worker
haveCommandsLocked() const1613*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::haveCommandsLocked() const {
1614*38e8c45fSAndroid Build Coastguard Worker return !mCommandQueue.empty();
1615*38e8c45fSAndroid Build Coastguard Worker }
1616*38e8c45fSAndroid Build Coastguard Worker
runCommandsLockedInterruptable()1617*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::runCommandsLockedInterruptable() {
1618*38e8c45fSAndroid Build Coastguard Worker if (mCommandQueue.empty()) {
1619*38e8c45fSAndroid Build Coastguard Worker return false;
1620*38e8c45fSAndroid Build Coastguard Worker }
1621*38e8c45fSAndroid Build Coastguard Worker
1622*38e8c45fSAndroid Build Coastguard Worker do {
1623*38e8c45fSAndroid Build Coastguard Worker auto command = std::move(mCommandQueue.front());
1624*38e8c45fSAndroid Build Coastguard Worker mCommandQueue.pop_front();
1625*38e8c45fSAndroid Build Coastguard Worker // Commands are run with the lock held, but may release and re-acquire the lock from within.
1626*38e8c45fSAndroid Build Coastguard Worker command();
1627*38e8c45fSAndroid Build Coastguard Worker } while (!mCommandQueue.empty());
1628*38e8c45fSAndroid Build Coastguard Worker return true;
1629*38e8c45fSAndroid Build Coastguard Worker }
1630*38e8c45fSAndroid Build Coastguard Worker
postCommandLocked(Command && command)1631*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::postCommandLocked(Command&& command) {
1632*38e8c45fSAndroid Build Coastguard Worker mCommandQueue.push_back(command);
1633*38e8c45fSAndroid Build Coastguard Worker }
1634*38e8c45fSAndroid Build Coastguard Worker
drainInboundQueueLocked()1635*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::drainInboundQueueLocked() {
1636*38e8c45fSAndroid Build Coastguard Worker while (!mInboundQueue.empty()) {
1637*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const EventEntry> entry = mInboundQueue.front();
1638*38e8c45fSAndroid Build Coastguard Worker mInboundQueue.pop_front();
1639*38e8c45fSAndroid Build Coastguard Worker releaseInboundEventLocked(entry);
1640*38e8c45fSAndroid Build Coastguard Worker }
1641*38e8c45fSAndroid Build Coastguard Worker traceInboundQueueLengthLocked();
1642*38e8c45fSAndroid Build Coastguard Worker }
1643*38e8c45fSAndroid Build Coastguard Worker
releasePendingEventLocked()1644*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::releasePendingEventLocked() {
1645*38e8c45fSAndroid Build Coastguard Worker if (mPendingEvent) {
1646*38e8c45fSAndroid Build Coastguard Worker releaseInboundEventLocked(mPendingEvent);
1647*38e8c45fSAndroid Build Coastguard Worker mPendingEvent = nullptr;
1648*38e8c45fSAndroid Build Coastguard Worker }
1649*38e8c45fSAndroid Build Coastguard Worker }
1650*38e8c45fSAndroid Build Coastguard Worker
releaseInboundEventLocked(std::shared_ptr<const EventEntry> entry)1651*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::releaseInboundEventLocked(std::shared_ptr<const EventEntry> entry) {
1652*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<InjectionState>& injectionState = entry->injectionState;
1653*38e8c45fSAndroid Build Coastguard Worker if (injectionState && injectionState->injectionResult == InputEventInjectionResult::PENDING) {
1654*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_DISPATCH_CYCLE) {
1655*38e8c45fSAndroid Build Coastguard Worker ALOGD("Injected inbound event was dropped.");
1656*38e8c45fSAndroid Build Coastguard Worker }
1657*38e8c45fSAndroid Build Coastguard Worker setInjectionResult(*entry, InputEventInjectionResult::FAILED);
1658*38e8c45fSAndroid Build Coastguard Worker }
1659*38e8c45fSAndroid Build Coastguard Worker if (entry == mNextUnblockedEvent) {
1660*38e8c45fSAndroid Build Coastguard Worker mNextUnblockedEvent = nullptr;
1661*38e8c45fSAndroid Build Coastguard Worker }
1662*38e8c45fSAndroid Build Coastguard Worker addRecentEventLocked(entry);
1663*38e8c45fSAndroid Build Coastguard Worker }
1664*38e8c45fSAndroid Build Coastguard Worker
resetKeyRepeatLocked()1665*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::resetKeyRepeatLocked() {
1666*38e8c45fSAndroid Build Coastguard Worker if (mKeyRepeatState.lastKeyEntry) {
1667*38e8c45fSAndroid Build Coastguard Worker mKeyRepeatState.lastKeyEntry = nullptr;
1668*38e8c45fSAndroid Build Coastguard Worker }
1669*38e8c45fSAndroid Build Coastguard Worker }
1670*38e8c45fSAndroid Build Coastguard Worker
synthesizeKeyRepeatLocked(nsecs_t currentTime)1671*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<KeyEntry> InputDispatcher::synthesizeKeyRepeatLocked(nsecs_t currentTime) {
1672*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const KeyEntry> entry = mKeyRepeatState.lastKeyEntry;
1673*38e8c45fSAndroid Build Coastguard Worker
1674*38e8c45fSAndroid Build Coastguard Worker uint32_t policyFlags = entry->policyFlags &
1675*38e8c45fSAndroid Build Coastguard Worker (POLICY_FLAG_RAW_MASK | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED);
1676*38e8c45fSAndroid Build Coastguard Worker
1677*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<KeyEntry> newEntry =
1678*38e8c45fSAndroid Build Coastguard Worker std::make_unique<KeyEntry>(mIdGenerator.nextId(), /*injectionState=*/nullptr,
1679*38e8c45fSAndroid Build Coastguard Worker currentTime, entry->deviceId, entry->source,
1680*38e8c45fSAndroid Build Coastguard Worker entry->displayId, policyFlags, entry->action, entry->flags,
1681*38e8c45fSAndroid Build Coastguard Worker entry->keyCode, entry->scanCode, entry->metaState,
1682*38e8c45fSAndroid Build Coastguard Worker entry->repeatCount + 1, entry->downTime);
1683*38e8c45fSAndroid Build Coastguard Worker
1684*38e8c45fSAndroid Build Coastguard Worker newEntry->syntheticRepeat = true;
1685*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
1686*38e8c45fSAndroid Build Coastguard Worker newEntry->traceTracker = mTracer->traceInboundEvent(*newEntry);
1687*38e8c45fSAndroid Build Coastguard Worker }
1688*38e8c45fSAndroid Build Coastguard Worker
1689*38e8c45fSAndroid Build Coastguard Worker mKeyRepeatState.lastKeyEntry = newEntry;
1690*38e8c45fSAndroid Build Coastguard Worker mKeyRepeatState.nextRepeatTime = currentTime + mConfig.keyRepeatDelay;
1691*38e8c45fSAndroid Build Coastguard Worker return newEntry;
1692*38e8c45fSAndroid Build Coastguard Worker }
1693*38e8c45fSAndroid Build Coastguard Worker
dispatchDeviceResetLocked(nsecs_t currentTime,const DeviceResetEntry & entry)1694*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::dispatchDeviceResetLocked(nsecs_t currentTime,
1695*38e8c45fSAndroid Build Coastguard Worker const DeviceResetEntry& entry) {
1696*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_OUTBOUND_EVENT_DETAILS) {
1697*38e8c45fSAndroid Build Coastguard Worker ALOGD("dispatchDeviceReset - eventTime=%" PRId64 ", deviceId=%d", entry.eventTime,
1698*38e8c45fSAndroid Build Coastguard Worker entry.deviceId);
1699*38e8c45fSAndroid Build Coastguard Worker }
1700*38e8c45fSAndroid Build Coastguard Worker
1701*38e8c45fSAndroid Build Coastguard Worker // Reset key repeating in case a keyboard device was disabled or enabled.
1702*38e8c45fSAndroid Build Coastguard Worker if (mKeyRepeatState.lastKeyEntry && mKeyRepeatState.lastKeyEntry->deviceId == entry.deviceId) {
1703*38e8c45fSAndroid Build Coastguard Worker resetKeyRepeatLocked();
1704*38e8c45fSAndroid Build Coastguard Worker }
1705*38e8c45fSAndroid Build Coastguard Worker
1706*38e8c45fSAndroid Build Coastguard Worker ScopedSyntheticEventTracer traceContext(mTracer);
1707*38e8c45fSAndroid Build Coastguard Worker CancelationOptions options(CancelationOptions::Mode::CANCEL_ALL_EVENTS, "device was reset",
1708*38e8c45fSAndroid Build Coastguard Worker traceContext.getTracker());
1709*38e8c45fSAndroid Build Coastguard Worker options.deviceId = entry.deviceId;
1710*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForAllConnectionsLocked(options);
1711*38e8c45fSAndroid Build Coastguard Worker
1712*38e8c45fSAndroid Build Coastguard Worker // Remove all active pointers from this device
1713*38e8c45fSAndroid Build Coastguard Worker for (auto& [_, touchState] : mTouchStatesByDisplay) {
1714*38e8c45fSAndroid Build Coastguard Worker touchState.removeAllPointersForDevice(entry.deviceId);
1715*38e8c45fSAndroid Build Coastguard Worker }
1716*38e8c45fSAndroid Build Coastguard Worker return true;
1717*38e8c45fSAndroid Build Coastguard Worker }
1718*38e8c45fSAndroid Build Coastguard Worker
enqueueFocusEventLocked(const sp<IBinder> & windowToken,bool hasFocus,const std::string & reason)1719*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::enqueueFocusEventLocked(const sp<IBinder>& windowToken, bool hasFocus,
1720*38e8c45fSAndroid Build Coastguard Worker const std::string& reason) {
1721*38e8c45fSAndroid Build Coastguard Worker if (mPendingEvent != nullptr) {
1722*38e8c45fSAndroid Build Coastguard Worker // Move the pending event to the front of the queue. This will give the chance
1723*38e8c45fSAndroid Build Coastguard Worker // for the pending event to get dispatched to the newly focused window
1724*38e8c45fSAndroid Build Coastguard Worker mInboundQueue.push_front(mPendingEvent);
1725*38e8c45fSAndroid Build Coastguard Worker mPendingEvent = nullptr;
1726*38e8c45fSAndroid Build Coastguard Worker }
1727*38e8c45fSAndroid Build Coastguard Worker
1728*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<FocusEntry> focusEntry =
1729*38e8c45fSAndroid Build Coastguard Worker std::make_unique<FocusEntry>(mIdGenerator.nextId(), now(), windowToken, hasFocus,
1730*38e8c45fSAndroid Build Coastguard Worker reason);
1731*38e8c45fSAndroid Build Coastguard Worker
1732*38e8c45fSAndroid Build Coastguard Worker // This event should go to the front of the queue, but behind all other focus events
1733*38e8c45fSAndroid Build Coastguard Worker // Find the last focus event, and insert right after it
1734*38e8c45fSAndroid Build Coastguard Worker auto it = std::find_if(mInboundQueue.rbegin(), mInboundQueue.rend(),
1735*38e8c45fSAndroid Build Coastguard Worker [](const std::shared_ptr<const EventEntry>& event) {
1736*38e8c45fSAndroid Build Coastguard Worker return event->type == EventEntry::Type::FOCUS;
1737*38e8c45fSAndroid Build Coastguard Worker });
1738*38e8c45fSAndroid Build Coastguard Worker
1739*38e8c45fSAndroid Build Coastguard Worker // Maintain the order of focus events. Insert the entry after all other focus events.
1740*38e8c45fSAndroid Build Coastguard Worker mInboundQueue.insert(it.base(), std::move(focusEntry));
1741*38e8c45fSAndroid Build Coastguard Worker }
1742*38e8c45fSAndroid Build Coastguard Worker
dispatchFocusLocked(nsecs_t currentTime,std::shared_ptr<const FocusEntry> entry)1743*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::dispatchFocusLocked(nsecs_t currentTime,
1744*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const FocusEntry> entry) {
1745*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<Connection> connection = getConnectionLocked(entry->connectionToken);
1746*38e8c45fSAndroid Build Coastguard Worker if (connection == nullptr) {
1747*38e8c45fSAndroid Build Coastguard Worker return; // Connection has gone away
1748*38e8c45fSAndroid Build Coastguard Worker }
1749*38e8c45fSAndroid Build Coastguard Worker entry->dispatchInProgress = true;
1750*38e8c45fSAndroid Build Coastguard Worker std::string message = std::string("Focus ") + (entry->hasFocus ? "entering " : "leaving ") +
1751*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName();
1752*38e8c45fSAndroid Build Coastguard Worker std::string reason = std::string("reason=").append(entry->reason);
1753*38e8c45fSAndroid Build Coastguard Worker android_log_event_list(LOGTAG_INPUT_FOCUS) << message << reason << LOG_ID_EVENTS;
1754*38e8c45fSAndroid Build Coastguard Worker dispatchEventLocked(currentTime, entry, {{connection}});
1755*38e8c45fSAndroid Build Coastguard Worker }
1756*38e8c45fSAndroid Build Coastguard Worker
dispatchPointerCaptureChangedLocked(nsecs_t currentTime,const std::shared_ptr<const PointerCaptureChangedEntry> & entry,DropReason & dropReason)1757*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::dispatchPointerCaptureChangedLocked(
1758*38e8c45fSAndroid Build Coastguard Worker nsecs_t currentTime, const std::shared_ptr<const PointerCaptureChangedEntry>& entry,
1759*38e8c45fSAndroid Build Coastguard Worker DropReason& dropReason) {
1760*38e8c45fSAndroid Build Coastguard Worker dropReason = DropReason::NOT_DROPPED;
1761*38e8c45fSAndroid Build Coastguard Worker
1762*38e8c45fSAndroid Build Coastguard Worker const bool haveWindowWithPointerCapture = mWindowTokenWithPointerCapture != nullptr;
1763*38e8c45fSAndroid Build Coastguard Worker sp<IBinder> token;
1764*38e8c45fSAndroid Build Coastguard Worker
1765*38e8c45fSAndroid Build Coastguard Worker if (entry->pointerCaptureRequest.isEnable()) {
1766*38e8c45fSAndroid Build Coastguard Worker // Enable Pointer Capture.
1767*38e8c45fSAndroid Build Coastguard Worker if (haveWindowWithPointerCapture &&
1768*38e8c45fSAndroid Build Coastguard Worker (entry->pointerCaptureRequest == mCurrentPointerCaptureRequest)) {
1769*38e8c45fSAndroid Build Coastguard Worker // This can happen if pointer capture is disabled and re-enabled before we notify the
1770*38e8c45fSAndroid Build Coastguard Worker // app of the state change, so there is no need to notify the app.
1771*38e8c45fSAndroid Build Coastguard Worker ALOGI("Skipping dispatch of Pointer Capture being enabled: no state change.");
1772*38e8c45fSAndroid Build Coastguard Worker return;
1773*38e8c45fSAndroid Build Coastguard Worker }
1774*38e8c45fSAndroid Build Coastguard Worker if (!mCurrentPointerCaptureRequest.isEnable()) {
1775*38e8c45fSAndroid Build Coastguard Worker // This can happen if a window requests capture and immediately releases capture.
1776*38e8c45fSAndroid Build Coastguard Worker ALOGW("No window requested Pointer Capture.");
1777*38e8c45fSAndroid Build Coastguard Worker dropReason = DropReason::NO_POINTER_CAPTURE;
1778*38e8c45fSAndroid Build Coastguard Worker return;
1779*38e8c45fSAndroid Build Coastguard Worker }
1780*38e8c45fSAndroid Build Coastguard Worker if (entry->pointerCaptureRequest.seq != mCurrentPointerCaptureRequest.seq) {
1781*38e8c45fSAndroid Build Coastguard Worker ALOGI("Skipping dispatch of Pointer Capture being enabled: sequence number mismatch.");
1782*38e8c45fSAndroid Build Coastguard Worker return;
1783*38e8c45fSAndroid Build Coastguard Worker }
1784*38e8c45fSAndroid Build Coastguard Worker
1785*38e8c45fSAndroid Build Coastguard Worker token = mFocusResolver.getFocusedWindowToken(mFocusedDisplayId);
1786*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(!token, "Cannot find focused window for Pointer Capture.");
1787*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(token != entry->pointerCaptureRequest.window,
1788*38e8c45fSAndroid Build Coastguard Worker "Unexpected requested window for Pointer Capture.");
1789*38e8c45fSAndroid Build Coastguard Worker mWindowTokenWithPointerCapture = token;
1790*38e8c45fSAndroid Build Coastguard Worker } else {
1791*38e8c45fSAndroid Build Coastguard Worker // Disable Pointer Capture.
1792*38e8c45fSAndroid Build Coastguard Worker // We do not check if the sequence number matches for requests to disable Pointer Capture
1793*38e8c45fSAndroid Build Coastguard Worker // for two reasons:
1794*38e8c45fSAndroid Build Coastguard Worker // 1. Pointer Capture can be disabled by a focus change, which means we can get two entries
1795*38e8c45fSAndroid Build Coastguard Worker // to disable capture with the same sequence number: one generated by
1796*38e8c45fSAndroid Build Coastguard Worker // disablePointerCaptureForcedLocked() and another as an acknowledgement of Pointer
1797*38e8c45fSAndroid Build Coastguard Worker // Capture being disabled in InputReader.
1798*38e8c45fSAndroid Build Coastguard Worker // 2. We respect any request to disable Pointer Capture generated by InputReader, since the
1799*38e8c45fSAndroid Build Coastguard Worker // actual Pointer Capture state that affects events being generated by input devices is
1800*38e8c45fSAndroid Build Coastguard Worker // in InputReader.
1801*38e8c45fSAndroid Build Coastguard Worker if (!haveWindowWithPointerCapture) {
1802*38e8c45fSAndroid Build Coastguard Worker // Pointer capture was already forcefully disabled because of focus change.
1803*38e8c45fSAndroid Build Coastguard Worker dropReason = DropReason::NOT_DROPPED;
1804*38e8c45fSAndroid Build Coastguard Worker return;
1805*38e8c45fSAndroid Build Coastguard Worker }
1806*38e8c45fSAndroid Build Coastguard Worker token = mWindowTokenWithPointerCapture;
1807*38e8c45fSAndroid Build Coastguard Worker mWindowTokenWithPointerCapture = nullptr;
1808*38e8c45fSAndroid Build Coastguard Worker if (mCurrentPointerCaptureRequest.isEnable()) {
1809*38e8c45fSAndroid Build Coastguard Worker setPointerCaptureLocked(nullptr);
1810*38e8c45fSAndroid Build Coastguard Worker }
1811*38e8c45fSAndroid Build Coastguard Worker }
1812*38e8c45fSAndroid Build Coastguard Worker
1813*38e8c45fSAndroid Build Coastguard Worker auto connection = getConnectionLocked(token);
1814*38e8c45fSAndroid Build Coastguard Worker if (connection == nullptr) {
1815*38e8c45fSAndroid Build Coastguard Worker // Window has gone away, clean up Pointer Capture state.
1816*38e8c45fSAndroid Build Coastguard Worker mWindowTokenWithPointerCapture = nullptr;
1817*38e8c45fSAndroid Build Coastguard Worker if (mCurrentPointerCaptureRequest.isEnable()) {
1818*38e8c45fSAndroid Build Coastguard Worker setPointerCaptureLocked(nullptr);
1819*38e8c45fSAndroid Build Coastguard Worker }
1820*38e8c45fSAndroid Build Coastguard Worker return;
1821*38e8c45fSAndroid Build Coastguard Worker }
1822*38e8c45fSAndroid Build Coastguard Worker entry->dispatchInProgress = true;
1823*38e8c45fSAndroid Build Coastguard Worker dispatchEventLocked(currentTime, entry, {{connection}});
1824*38e8c45fSAndroid Build Coastguard Worker
1825*38e8c45fSAndroid Build Coastguard Worker dropReason = DropReason::NOT_DROPPED;
1826*38e8c45fSAndroid Build Coastguard Worker }
1827*38e8c45fSAndroid Build Coastguard Worker
dispatchTouchModeChangeLocked(nsecs_t currentTime,const std::shared_ptr<const TouchModeEntry> & entry)1828*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::dispatchTouchModeChangeLocked(
1829*38e8c45fSAndroid Build Coastguard Worker nsecs_t currentTime, const std::shared_ptr<const TouchModeEntry>& entry) {
1830*38e8c45fSAndroid Build Coastguard Worker const std::vector<sp<WindowInfoHandle>>& windowHandles =
1831*38e8c45fSAndroid Build Coastguard Worker getWindowHandlesLocked(entry->displayId);
1832*38e8c45fSAndroid Build Coastguard Worker if (windowHandles.empty()) {
1833*38e8c45fSAndroid Build Coastguard Worker return;
1834*38e8c45fSAndroid Build Coastguard Worker }
1835*38e8c45fSAndroid Build Coastguard Worker const std::vector<InputTarget> inputTargets =
1836*38e8c45fSAndroid Build Coastguard Worker getInputTargetsFromWindowHandlesLocked(windowHandles);
1837*38e8c45fSAndroid Build Coastguard Worker if (inputTargets.empty()) {
1838*38e8c45fSAndroid Build Coastguard Worker return;
1839*38e8c45fSAndroid Build Coastguard Worker }
1840*38e8c45fSAndroid Build Coastguard Worker entry->dispatchInProgress = true;
1841*38e8c45fSAndroid Build Coastguard Worker dispatchEventLocked(currentTime, entry, inputTargets);
1842*38e8c45fSAndroid Build Coastguard Worker }
1843*38e8c45fSAndroid Build Coastguard Worker
getInputTargetsFromWindowHandlesLocked(const std::vector<sp<WindowInfoHandle>> & windowHandles) const1844*38e8c45fSAndroid Build Coastguard Worker std::vector<InputTarget> InputDispatcher::getInputTargetsFromWindowHandlesLocked(
1845*38e8c45fSAndroid Build Coastguard Worker const std::vector<sp<WindowInfoHandle>>& windowHandles) const {
1846*38e8c45fSAndroid Build Coastguard Worker std::vector<InputTarget> inputTargets;
1847*38e8c45fSAndroid Build Coastguard Worker for (const sp<WindowInfoHandle>& handle : windowHandles) {
1848*38e8c45fSAndroid Build Coastguard Worker const sp<IBinder>& token = handle->getToken();
1849*38e8c45fSAndroid Build Coastguard Worker if (token == nullptr) {
1850*38e8c45fSAndroid Build Coastguard Worker continue;
1851*38e8c45fSAndroid Build Coastguard Worker }
1852*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<Connection> connection = getConnectionLocked(token);
1853*38e8c45fSAndroid Build Coastguard Worker if (connection == nullptr) {
1854*38e8c45fSAndroid Build Coastguard Worker continue; // Connection has gone away
1855*38e8c45fSAndroid Build Coastguard Worker }
1856*38e8c45fSAndroid Build Coastguard Worker inputTargets.emplace_back(connection);
1857*38e8c45fSAndroid Build Coastguard Worker }
1858*38e8c45fSAndroid Build Coastguard Worker return inputTargets;
1859*38e8c45fSAndroid Build Coastguard Worker }
1860*38e8c45fSAndroid Build Coastguard Worker
dispatchKeyLocked(nsecs_t currentTime,std::shared_ptr<const KeyEntry> entry,DropReason * dropReason,nsecs_t & nextWakeupTime)1861*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<const KeyEntry> entry,
1862*38e8c45fSAndroid Build Coastguard Worker DropReason* dropReason, nsecs_t& nextWakeupTime) {
1863*38e8c45fSAndroid Build Coastguard Worker // Preprocessing.
1864*38e8c45fSAndroid Build Coastguard Worker if (!entry->dispatchInProgress) {
1865*38e8c45fSAndroid Build Coastguard Worker if (!entry->syntheticRepeat && entry->action == AKEY_EVENT_ACTION_DOWN &&
1866*38e8c45fSAndroid Build Coastguard Worker (entry->policyFlags & POLICY_FLAG_TRUSTED) &&
1867*38e8c45fSAndroid Build Coastguard Worker (!(entry->policyFlags & POLICY_FLAG_DISABLE_KEY_REPEAT))) {
1868*38e8c45fSAndroid Build Coastguard Worker if (mKeyRepeatState.lastKeyEntry &&
1869*38e8c45fSAndroid Build Coastguard Worker mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode &&
1870*38e8c45fSAndroid Build Coastguard Worker // We have seen two identical key downs in a row which indicates that the device
1871*38e8c45fSAndroid Build Coastguard Worker // driver is automatically generating key repeats itself. We take note of the
1872*38e8c45fSAndroid Build Coastguard Worker // repeat here, but we disable our own next key repeat timer since it is clear that
1873*38e8c45fSAndroid Build Coastguard Worker // we will not need to synthesize key repeats ourselves.
1874*38e8c45fSAndroid Build Coastguard Worker mKeyRepeatState.lastKeyEntry->deviceId == entry->deviceId) {
1875*38e8c45fSAndroid Build Coastguard Worker // Make sure we don't get key down from a different device. If a different
1876*38e8c45fSAndroid Build Coastguard Worker // device Id has same key pressed down, the new device Id will replace the
1877*38e8c45fSAndroid Build Coastguard Worker // current one to hold the key repeat with repeat count reset.
1878*38e8c45fSAndroid Build Coastguard Worker // In the future when got a KEY_UP on the device id, drop it and do not
1879*38e8c45fSAndroid Build Coastguard Worker // stop the key repeat on current device.
1880*38e8c45fSAndroid Build Coastguard Worker entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
1881*38e8c45fSAndroid Build Coastguard Worker resetKeyRepeatLocked();
1882*38e8c45fSAndroid Build Coastguard Worker mKeyRepeatState.nextRepeatTime = LLONG_MAX; // don't generate repeats ourselves
1883*38e8c45fSAndroid Build Coastguard Worker } else {
1884*38e8c45fSAndroid Build Coastguard Worker // Not a repeat. Save key down state in case we do see a repeat later.
1885*38e8c45fSAndroid Build Coastguard Worker resetKeyRepeatLocked();
1886*38e8c45fSAndroid Build Coastguard Worker mKeyRepeatState.nextRepeatTime = entry->eventTime + mConfig.keyRepeatTimeout;
1887*38e8c45fSAndroid Build Coastguard Worker }
1888*38e8c45fSAndroid Build Coastguard Worker mKeyRepeatState.lastKeyEntry = entry;
1889*38e8c45fSAndroid Build Coastguard Worker } else if (entry->action == AKEY_EVENT_ACTION_UP && mKeyRepeatState.lastKeyEntry &&
1890*38e8c45fSAndroid Build Coastguard Worker mKeyRepeatState.lastKeyEntry->deviceId != entry->deviceId) {
1891*38e8c45fSAndroid Build Coastguard Worker // The key on device 'deviceId' is still down, do not stop key repeat
1892*38e8c45fSAndroid Build Coastguard Worker if (debugInboundEventDetails()) {
1893*38e8c45fSAndroid Build Coastguard Worker ALOGD("deviceId=%d got KEY_UP as stale", entry->deviceId);
1894*38e8c45fSAndroid Build Coastguard Worker }
1895*38e8c45fSAndroid Build Coastguard Worker } else if (!entry->syntheticRepeat) {
1896*38e8c45fSAndroid Build Coastguard Worker resetKeyRepeatLocked();
1897*38e8c45fSAndroid Build Coastguard Worker }
1898*38e8c45fSAndroid Build Coastguard Worker
1899*38e8c45fSAndroid Build Coastguard Worker if (entry->repeatCount == 1) {
1900*38e8c45fSAndroid Build Coastguard Worker entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
1901*38e8c45fSAndroid Build Coastguard Worker } else {
1902*38e8c45fSAndroid Build Coastguard Worker entry->flags &= ~AKEY_EVENT_FLAG_LONG_PRESS;
1903*38e8c45fSAndroid Build Coastguard Worker }
1904*38e8c45fSAndroid Build Coastguard Worker
1905*38e8c45fSAndroid Build Coastguard Worker entry->dispatchInProgress = true;
1906*38e8c45fSAndroid Build Coastguard Worker
1907*38e8c45fSAndroid Build Coastguard Worker logOutboundKeyDetails("dispatchKey - ", *entry);
1908*38e8c45fSAndroid Build Coastguard Worker }
1909*38e8c45fSAndroid Build Coastguard Worker
1910*38e8c45fSAndroid Build Coastguard Worker // Handle case where the policy asked us to try again later last time.
1911*38e8c45fSAndroid Build Coastguard Worker if (entry->interceptKeyResult == KeyEntry::InterceptKeyResult::TRY_AGAIN_LATER) {
1912*38e8c45fSAndroid Build Coastguard Worker if (currentTime < entry->interceptKeyWakeupTime) {
1913*38e8c45fSAndroid Build Coastguard Worker nextWakeupTime = std::min(nextWakeupTime, entry->interceptKeyWakeupTime);
1914*38e8c45fSAndroid Build Coastguard Worker return false; // wait until next wakeup
1915*38e8c45fSAndroid Build Coastguard Worker }
1916*38e8c45fSAndroid Build Coastguard Worker entry->interceptKeyResult = KeyEntry::InterceptKeyResult::UNKNOWN;
1917*38e8c45fSAndroid Build Coastguard Worker entry->interceptKeyWakeupTime = 0;
1918*38e8c45fSAndroid Build Coastguard Worker }
1919*38e8c45fSAndroid Build Coastguard Worker
1920*38e8c45fSAndroid Build Coastguard Worker // Give the policy a chance to intercept the key.
1921*38e8c45fSAndroid Build Coastguard Worker if (entry->interceptKeyResult == KeyEntry::InterceptKeyResult::UNKNOWN) {
1922*38e8c45fSAndroid Build Coastguard Worker if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
1923*38e8c45fSAndroid Build Coastguard Worker sp<IBinder> focusedWindowToken =
1924*38e8c45fSAndroid Build Coastguard Worker mFocusResolver.getFocusedWindowToken(getTargetDisplayId(*entry));
1925*38e8c45fSAndroid Build Coastguard Worker
1926*38e8c45fSAndroid Build Coastguard Worker auto command = [this, focusedWindowToken, entry]() REQUIRES(mLock) {
1927*38e8c45fSAndroid Build Coastguard Worker doInterceptKeyBeforeDispatchingCommand(focusedWindowToken, *entry);
1928*38e8c45fSAndroid Build Coastguard Worker };
1929*38e8c45fSAndroid Build Coastguard Worker postCommandLocked(std::move(command));
1930*38e8c45fSAndroid Build Coastguard Worker return false; // wait for the command to run
1931*38e8c45fSAndroid Build Coastguard Worker } else {
1932*38e8c45fSAndroid Build Coastguard Worker entry->interceptKeyResult = KeyEntry::InterceptKeyResult::CONTINUE;
1933*38e8c45fSAndroid Build Coastguard Worker }
1934*38e8c45fSAndroid Build Coastguard Worker } else if (entry->interceptKeyResult == KeyEntry::InterceptKeyResult::SKIP) {
1935*38e8c45fSAndroid Build Coastguard Worker if (*dropReason == DropReason::NOT_DROPPED) {
1936*38e8c45fSAndroid Build Coastguard Worker *dropReason = DropReason::POLICY;
1937*38e8c45fSAndroid Build Coastguard Worker }
1938*38e8c45fSAndroid Build Coastguard Worker }
1939*38e8c45fSAndroid Build Coastguard Worker
1940*38e8c45fSAndroid Build Coastguard Worker // Clean up if dropping the event.
1941*38e8c45fSAndroid Build Coastguard Worker if (*dropReason != DropReason::NOT_DROPPED) {
1942*38e8c45fSAndroid Build Coastguard Worker setInjectionResult(*entry,
1943*38e8c45fSAndroid Build Coastguard Worker *dropReason == DropReason::POLICY ? InputEventInjectionResult::SUCCEEDED
1944*38e8c45fSAndroid Build Coastguard Worker : InputEventInjectionResult::FAILED);
1945*38e8c45fSAndroid Build Coastguard Worker mReporter->reportDroppedKey(entry->id);
1946*38e8c45fSAndroid Build Coastguard Worker // Poke user activity for consumed keys, as it may have not been reported due to
1947*38e8c45fSAndroid Build Coastguard Worker // the focused window requesting user activity to be disabled
1948*38e8c45fSAndroid Build Coastguard Worker if (*dropReason == DropReason::POLICY &&
1949*38e8c45fSAndroid Build Coastguard Worker mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
1950*38e8c45fSAndroid Build Coastguard Worker pokeUserActivityLocked(*entry);
1951*38e8c45fSAndroid Build Coastguard Worker }
1952*38e8c45fSAndroid Build Coastguard Worker return true;
1953*38e8c45fSAndroid Build Coastguard Worker }
1954*38e8c45fSAndroid Build Coastguard Worker
1955*38e8c45fSAndroid Build Coastguard Worker // Identify targets.
1956*38e8c45fSAndroid Build Coastguard Worker Result<sp<WindowInfoHandle>, InputEventInjectionResult> result =
1957*38e8c45fSAndroid Build Coastguard Worker findFocusedWindowTargetLocked(currentTime, *entry, nextWakeupTime);
1958*38e8c45fSAndroid Build Coastguard Worker
1959*38e8c45fSAndroid Build Coastguard Worker if (!result.ok()) {
1960*38e8c45fSAndroid Build Coastguard Worker if (result.error().code() == InputEventInjectionResult::PENDING) {
1961*38e8c45fSAndroid Build Coastguard Worker return false;
1962*38e8c45fSAndroid Build Coastguard Worker }
1963*38e8c45fSAndroid Build Coastguard Worker setInjectionResult(*entry, result.error().code());
1964*38e8c45fSAndroid Build Coastguard Worker return true;
1965*38e8c45fSAndroid Build Coastguard Worker }
1966*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle>& focusedWindow = *result;
1967*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(focusedWindow == nullptr);
1968*38e8c45fSAndroid Build Coastguard Worker
1969*38e8c45fSAndroid Build Coastguard Worker setInjectionResult(*entry, InputEventInjectionResult::SUCCEEDED);
1970*38e8c45fSAndroid Build Coastguard Worker
1971*38e8c45fSAndroid Build Coastguard Worker std::vector<InputTarget> inputTargets;
1972*38e8c45fSAndroid Build Coastguard Worker addWindowTargetLocked(focusedWindow, InputTarget::DispatchMode::AS_IS,
1973*38e8c45fSAndroid Build Coastguard Worker InputTarget::Flags::FOREGROUND, getDownTime(*entry), inputTargets);
1974*38e8c45fSAndroid Build Coastguard Worker
1975*38e8c45fSAndroid Build Coastguard Worker // Add monitor channels from event's or focused display.
1976*38e8c45fSAndroid Build Coastguard Worker addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));
1977*38e8c45fSAndroid Build Coastguard Worker
1978*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
1979*38e8c45fSAndroid Build Coastguard Worker ensureEventTraced(*entry);
1980*38e8c45fSAndroid Build Coastguard Worker for (const auto& target : inputTargets) {
1981*38e8c45fSAndroid Build Coastguard Worker mTracer->dispatchToTargetHint(*entry->traceTracker, target);
1982*38e8c45fSAndroid Build Coastguard Worker }
1983*38e8c45fSAndroid Build Coastguard Worker }
1984*38e8c45fSAndroid Build Coastguard Worker
1985*38e8c45fSAndroid Build Coastguard Worker // Dispatch the key.
1986*38e8c45fSAndroid Build Coastguard Worker dispatchEventLocked(currentTime, entry, inputTargets);
1987*38e8c45fSAndroid Build Coastguard Worker return true;
1988*38e8c45fSAndroid Build Coastguard Worker }
1989*38e8c45fSAndroid Build Coastguard Worker
logOutboundKeyDetails(const char * prefix,const KeyEntry & entry)1990*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::logOutboundKeyDetails(const char* prefix, const KeyEntry& entry) {
1991*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_OUTBOUND_EVENT_DETAILS) {
1992*38e8c45fSAndroid Build Coastguard Worker ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%s, "
1993*38e8c45fSAndroid Build Coastguard Worker "policyFlags=0x%x, action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, "
1994*38e8c45fSAndroid Build Coastguard Worker "metaState=0x%x, repeatCount=%d, downTime=%" PRId64,
1995*38e8c45fSAndroid Build Coastguard Worker prefix, entry.eventTime, entry.deviceId, entry.source,
1996*38e8c45fSAndroid Build Coastguard Worker entry.displayId.toString().c_str(), entry.policyFlags, entry.action, entry.flags,
1997*38e8c45fSAndroid Build Coastguard Worker entry.keyCode, entry.scanCode, entry.metaState, entry.repeatCount, entry.downTime);
1998*38e8c45fSAndroid Build Coastguard Worker }
1999*38e8c45fSAndroid Build Coastguard Worker }
2000*38e8c45fSAndroid Build Coastguard Worker
dispatchSensorLocked(nsecs_t currentTime,const std::shared_ptr<const SensorEntry> & entry,DropReason * dropReason,nsecs_t & nextWakeupTime)2001*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::dispatchSensorLocked(nsecs_t currentTime,
2002*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<const SensorEntry>& entry,
2003*38e8c45fSAndroid Build Coastguard Worker DropReason* dropReason, nsecs_t& nextWakeupTime) {
2004*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_OUTBOUND_EVENT_DETAILS) {
2005*38e8c45fSAndroid Build Coastguard Worker ALOGD("notifySensorEvent eventTime=%" PRId64 ", hwTimestamp=%" PRId64 ", deviceId=%d, "
2006*38e8c45fSAndroid Build Coastguard Worker "source=0x%x, sensorType=%s",
2007*38e8c45fSAndroid Build Coastguard Worker entry->eventTime, entry->hwTimestamp, entry->deviceId, entry->source,
2008*38e8c45fSAndroid Build Coastguard Worker ftl::enum_string(entry->sensorType).c_str());
2009*38e8c45fSAndroid Build Coastguard Worker }
2010*38e8c45fSAndroid Build Coastguard Worker auto command = [this, entry]() REQUIRES(mLock) {
2011*38e8c45fSAndroid Build Coastguard Worker scoped_unlock unlock(mLock);
2012*38e8c45fSAndroid Build Coastguard Worker
2013*38e8c45fSAndroid Build Coastguard Worker if (entry->accuracyChanged) {
2014*38e8c45fSAndroid Build Coastguard Worker mPolicy.notifySensorAccuracy(entry->deviceId, entry->sensorType, entry->accuracy);
2015*38e8c45fSAndroid Build Coastguard Worker }
2016*38e8c45fSAndroid Build Coastguard Worker mPolicy.notifySensorEvent(entry->deviceId, entry->sensorType, entry->accuracy,
2017*38e8c45fSAndroid Build Coastguard Worker entry->hwTimestamp, entry->values);
2018*38e8c45fSAndroid Build Coastguard Worker };
2019*38e8c45fSAndroid Build Coastguard Worker postCommandLocked(std::move(command));
2020*38e8c45fSAndroid Build Coastguard Worker }
2021*38e8c45fSAndroid Build Coastguard Worker
flushSensor(int deviceId,InputDeviceSensorType sensorType)2022*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::flushSensor(int deviceId, InputDeviceSensorType sensorType) {
2023*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_OUTBOUND_EVENT_DETAILS) {
2024*38e8c45fSAndroid Build Coastguard Worker ALOGD("flushSensor deviceId=%d, sensorType=%s", deviceId,
2025*38e8c45fSAndroid Build Coastguard Worker ftl::enum_string(sensorType).c_str());
2026*38e8c45fSAndroid Build Coastguard Worker }
2027*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
2028*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
2029*38e8c45fSAndroid Build Coastguard Worker
2030*38e8c45fSAndroid Build Coastguard Worker for (auto it = mInboundQueue.begin(); it != mInboundQueue.end(); it++) {
2031*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const EventEntry> entry = *it;
2032*38e8c45fSAndroid Build Coastguard Worker if (entry->type == EventEntry::Type::SENSOR) {
2033*38e8c45fSAndroid Build Coastguard Worker it = mInboundQueue.erase(it);
2034*38e8c45fSAndroid Build Coastguard Worker releaseInboundEventLocked(entry);
2035*38e8c45fSAndroid Build Coastguard Worker }
2036*38e8c45fSAndroid Build Coastguard Worker }
2037*38e8c45fSAndroid Build Coastguard Worker }
2038*38e8c45fSAndroid Build Coastguard Worker return true;
2039*38e8c45fSAndroid Build Coastguard Worker }
2040*38e8c45fSAndroid Build Coastguard Worker
dispatchMotionLocked(nsecs_t currentTime,std::shared_ptr<const MotionEntry> entry,DropReason * dropReason,nsecs_t & nextWakeupTime)2041*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime,
2042*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const MotionEntry> entry,
2043*38e8c45fSAndroid Build Coastguard Worker DropReason* dropReason, nsecs_t& nextWakeupTime) {
2044*38e8c45fSAndroid Build Coastguard Worker ATRACE_CALL();
2045*38e8c45fSAndroid Build Coastguard Worker // Preprocessing.
2046*38e8c45fSAndroid Build Coastguard Worker if (!entry->dispatchInProgress) {
2047*38e8c45fSAndroid Build Coastguard Worker entry->dispatchInProgress = true;
2048*38e8c45fSAndroid Build Coastguard Worker
2049*38e8c45fSAndroid Build Coastguard Worker logOutboundMotionDetails("dispatchMotion - ", *entry);
2050*38e8c45fSAndroid Build Coastguard Worker }
2051*38e8c45fSAndroid Build Coastguard Worker
2052*38e8c45fSAndroid Build Coastguard Worker // Clean up if dropping the event.
2053*38e8c45fSAndroid Build Coastguard Worker if (*dropReason != DropReason::NOT_DROPPED) {
2054*38e8c45fSAndroid Build Coastguard Worker setInjectionResult(*entry,
2055*38e8c45fSAndroid Build Coastguard Worker *dropReason == DropReason::POLICY ? InputEventInjectionResult::SUCCEEDED
2056*38e8c45fSAndroid Build Coastguard Worker : InputEventInjectionResult::FAILED);
2057*38e8c45fSAndroid Build Coastguard Worker return true;
2058*38e8c45fSAndroid Build Coastguard Worker }
2059*38e8c45fSAndroid Build Coastguard Worker
2060*38e8c45fSAndroid Build Coastguard Worker const bool isPointerEvent = isFromSource(entry->source, AINPUT_SOURCE_CLASS_POINTER);
2061*38e8c45fSAndroid Build Coastguard Worker
2062*38e8c45fSAndroid Build Coastguard Worker // Identify targets.
2063*38e8c45fSAndroid Build Coastguard Worker std::vector<InputTarget> inputTargets;
2064*38e8c45fSAndroid Build Coastguard Worker
2065*38e8c45fSAndroid Build Coastguard Worker InputEventInjectionResult injectionResult;
2066*38e8c45fSAndroid Build Coastguard Worker if (isPointerEvent) {
2067*38e8c45fSAndroid Build Coastguard Worker // Pointer event. (eg. touchscreen)
2068*38e8c45fSAndroid Build Coastguard Worker
2069*38e8c45fSAndroid Build Coastguard Worker if (mDragState &&
2070*38e8c45fSAndroid Build Coastguard Worker (entry->action & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_POINTER_DOWN) {
2071*38e8c45fSAndroid Build Coastguard Worker // If drag and drop ongoing and pointer down occur: pilfer drag window pointers
2072*38e8c45fSAndroid Build Coastguard Worker pilferPointersLocked(mDragState->dragWindow->getToken());
2073*38e8c45fSAndroid Build Coastguard Worker }
2074*38e8c45fSAndroid Build Coastguard Worker
2075*38e8c45fSAndroid Build Coastguard Worker Result<std::vector<InputTarget>, InputEventInjectionResult> result =
2076*38e8c45fSAndroid Build Coastguard Worker findTouchedWindowTargetsLocked(currentTime, *entry);
2077*38e8c45fSAndroid Build Coastguard Worker
2078*38e8c45fSAndroid Build Coastguard Worker if (result.ok()) {
2079*38e8c45fSAndroid Build Coastguard Worker inputTargets = std::move(*result);
2080*38e8c45fSAndroid Build Coastguard Worker injectionResult = InputEventInjectionResult::SUCCEEDED;
2081*38e8c45fSAndroid Build Coastguard Worker } else {
2082*38e8c45fSAndroid Build Coastguard Worker injectionResult = result.error().code();
2083*38e8c45fSAndroid Build Coastguard Worker }
2084*38e8c45fSAndroid Build Coastguard Worker } else {
2085*38e8c45fSAndroid Build Coastguard Worker // Non touch event. (eg. trackball)
2086*38e8c45fSAndroid Build Coastguard Worker Result<sp<WindowInfoHandle>, InputEventInjectionResult> result =
2087*38e8c45fSAndroid Build Coastguard Worker findFocusedWindowTargetLocked(currentTime, *entry, nextWakeupTime);
2088*38e8c45fSAndroid Build Coastguard Worker if (result.ok()) {
2089*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle>& focusedWindow = *result;
2090*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(focusedWindow == nullptr);
2091*38e8c45fSAndroid Build Coastguard Worker addWindowTargetLocked(focusedWindow, InputTarget::DispatchMode::AS_IS,
2092*38e8c45fSAndroid Build Coastguard Worker InputTarget::Flags::FOREGROUND, getDownTime(*entry),
2093*38e8c45fSAndroid Build Coastguard Worker inputTargets);
2094*38e8c45fSAndroid Build Coastguard Worker injectionResult = InputEventInjectionResult::SUCCEEDED;
2095*38e8c45fSAndroid Build Coastguard Worker } else {
2096*38e8c45fSAndroid Build Coastguard Worker injectionResult = result.error().code();
2097*38e8c45fSAndroid Build Coastguard Worker }
2098*38e8c45fSAndroid Build Coastguard Worker }
2099*38e8c45fSAndroid Build Coastguard Worker if (injectionResult == InputEventInjectionResult::PENDING) {
2100*38e8c45fSAndroid Build Coastguard Worker return false;
2101*38e8c45fSAndroid Build Coastguard Worker }
2102*38e8c45fSAndroid Build Coastguard Worker
2103*38e8c45fSAndroid Build Coastguard Worker setInjectionResult(*entry, injectionResult);
2104*38e8c45fSAndroid Build Coastguard Worker if (injectionResult == InputEventInjectionResult::TARGET_MISMATCH) {
2105*38e8c45fSAndroid Build Coastguard Worker return true;
2106*38e8c45fSAndroid Build Coastguard Worker }
2107*38e8c45fSAndroid Build Coastguard Worker if (injectionResult != InputEventInjectionResult::SUCCEEDED) {
2108*38e8c45fSAndroid Build Coastguard Worker CancelationOptions::Mode mode(
2109*38e8c45fSAndroid Build Coastguard Worker isPointerEvent ? CancelationOptions::Mode::CANCEL_POINTER_EVENTS
2110*38e8c45fSAndroid Build Coastguard Worker : CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS);
2111*38e8c45fSAndroid Build Coastguard Worker CancelationOptions options(mode, "input event injection failed", entry->traceTracker);
2112*38e8c45fSAndroid Build Coastguard Worker options.displayId = entry->displayId;
2113*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForMonitorsLocked(options);
2114*38e8c45fSAndroid Build Coastguard Worker return true;
2115*38e8c45fSAndroid Build Coastguard Worker }
2116*38e8c45fSAndroid Build Coastguard Worker
2117*38e8c45fSAndroid Build Coastguard Worker // Add monitor channels from event's or focused display.
2118*38e8c45fSAndroid Build Coastguard Worker addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));
2119*38e8c45fSAndroid Build Coastguard Worker
2120*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
2121*38e8c45fSAndroid Build Coastguard Worker ensureEventTraced(*entry);
2122*38e8c45fSAndroid Build Coastguard Worker for (const auto& target : inputTargets) {
2123*38e8c45fSAndroid Build Coastguard Worker mTracer->dispatchToTargetHint(*entry->traceTracker, target);
2124*38e8c45fSAndroid Build Coastguard Worker }
2125*38e8c45fSAndroid Build Coastguard Worker }
2126*38e8c45fSAndroid Build Coastguard Worker
2127*38e8c45fSAndroid Build Coastguard Worker // Dispatch the motion.
2128*38e8c45fSAndroid Build Coastguard Worker dispatchEventLocked(currentTime, entry, inputTargets);
2129*38e8c45fSAndroid Build Coastguard Worker return true;
2130*38e8c45fSAndroid Build Coastguard Worker }
2131*38e8c45fSAndroid Build Coastguard Worker
enqueueDragEventLocked(const sp<WindowInfoHandle> & windowHandle,bool isExiting,const int32_t rawX,const int32_t rawY)2132*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::enqueueDragEventLocked(const sp<WindowInfoHandle>& windowHandle,
2133*38e8c45fSAndroid Build Coastguard Worker bool isExiting, const int32_t rawX,
2134*38e8c45fSAndroid Build Coastguard Worker const int32_t rawY) {
2135*38e8c45fSAndroid Build Coastguard Worker const vec2 xy = windowHandle->getInfo()->transform.transform(vec2(rawX, rawY));
2136*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<DragEntry> dragEntry =
2137*38e8c45fSAndroid Build Coastguard Worker std::make_unique<DragEntry>(mIdGenerator.nextId(), now(), windowHandle->getToken(),
2138*38e8c45fSAndroid Build Coastguard Worker isExiting, xy.x, xy.y);
2139*38e8c45fSAndroid Build Coastguard Worker
2140*38e8c45fSAndroid Build Coastguard Worker enqueueInboundEventLocked(std::move(dragEntry));
2141*38e8c45fSAndroid Build Coastguard Worker }
2142*38e8c45fSAndroid Build Coastguard Worker
dispatchDragLocked(nsecs_t currentTime,std::shared_ptr<const DragEntry> entry)2143*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::dispatchDragLocked(nsecs_t currentTime,
2144*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const DragEntry> entry) {
2145*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<Connection> connection = getConnectionLocked(entry->connectionToken);
2146*38e8c45fSAndroid Build Coastguard Worker if (connection == nullptr) {
2147*38e8c45fSAndroid Build Coastguard Worker return; // Connection has gone away
2148*38e8c45fSAndroid Build Coastguard Worker }
2149*38e8c45fSAndroid Build Coastguard Worker entry->dispatchInProgress = true;
2150*38e8c45fSAndroid Build Coastguard Worker dispatchEventLocked(currentTime, entry, {{connection}});
2151*38e8c45fSAndroid Build Coastguard Worker }
2152*38e8c45fSAndroid Build Coastguard Worker
logOutboundMotionDetails(const char * prefix,const MotionEntry & entry)2153*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::logOutboundMotionDetails(const char* prefix, const MotionEntry& entry) {
2154*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_OUTBOUND_EVENT_DETAILS) {
2155*38e8c45fSAndroid Build Coastguard Worker ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=%s, displayId=%s, policyFlags=0x%x, "
2156*38e8c45fSAndroid Build Coastguard Worker "action=%s, actionButton=0x%x, flags=0x%x, "
2157*38e8c45fSAndroid Build Coastguard Worker "metaState=0x%x, buttonState=0x%x, downTime=%" PRId64,
2158*38e8c45fSAndroid Build Coastguard Worker prefix, entry.eventTime, entry.deviceId,
2159*38e8c45fSAndroid Build Coastguard Worker inputEventSourceToString(entry.source).c_str(), entry.displayId.toString().c_str(),
2160*38e8c45fSAndroid Build Coastguard Worker entry.policyFlags, MotionEvent::actionToString(entry.action).c_str(),
2161*38e8c45fSAndroid Build Coastguard Worker entry.actionButton, entry.flags, entry.metaState, entry.buttonState, entry.downTime);
2162*38e8c45fSAndroid Build Coastguard Worker
2163*38e8c45fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < entry.getPointerCount(); i++) {
2164*38e8c45fSAndroid Build Coastguard Worker ALOGD(" Pointer %d: id=%d, toolType=%s, "
2165*38e8c45fSAndroid Build Coastguard Worker "x=%f, y=%f, pressure=%f, size=%f, "
2166*38e8c45fSAndroid Build Coastguard Worker "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, orientation=%f",
2167*38e8c45fSAndroid Build Coastguard Worker i, entry.pointerProperties[i].id,
2168*38e8c45fSAndroid Build Coastguard Worker ftl::enum_string(entry.pointerProperties[i].toolType).c_str(),
2169*38e8c45fSAndroid Build Coastguard Worker entry.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
2170*38e8c45fSAndroid Build Coastguard Worker entry.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
2171*38e8c45fSAndroid Build Coastguard Worker entry.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
2172*38e8c45fSAndroid Build Coastguard Worker entry.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
2173*38e8c45fSAndroid Build Coastguard Worker entry.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
2174*38e8c45fSAndroid Build Coastguard Worker entry.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
2175*38e8c45fSAndroid Build Coastguard Worker entry.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
2176*38e8c45fSAndroid Build Coastguard Worker entry.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
2177*38e8c45fSAndroid Build Coastguard Worker entry.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
2178*38e8c45fSAndroid Build Coastguard Worker }
2179*38e8c45fSAndroid Build Coastguard Worker }
2180*38e8c45fSAndroid Build Coastguard Worker }
2181*38e8c45fSAndroid Build Coastguard Worker
dispatchEventLocked(nsecs_t currentTime,std::shared_ptr<const EventEntry> eventEntry,const std::vector<InputTarget> & inputTargets)2182*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
2183*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const EventEntry> eventEntry,
2184*38e8c45fSAndroid Build Coastguard Worker const std::vector<InputTarget>& inputTargets) {
2185*38e8c45fSAndroid Build Coastguard Worker ATRACE_CALL();
2186*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_DISPATCH_CYCLE) {
2187*38e8c45fSAndroid Build Coastguard Worker ALOGD("dispatchEventToCurrentInputTargets");
2188*38e8c45fSAndroid Build Coastguard Worker }
2189*38e8c45fSAndroid Build Coastguard Worker
2190*38e8c45fSAndroid Build Coastguard Worker processInteractionsLocked(*eventEntry, inputTargets);
2191*38e8c45fSAndroid Build Coastguard Worker
2192*38e8c45fSAndroid Build Coastguard Worker ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
2193*38e8c45fSAndroid Build Coastguard Worker
2194*38e8c45fSAndroid Build Coastguard Worker pokeUserActivityLocked(*eventEntry);
2195*38e8c45fSAndroid Build Coastguard Worker
2196*38e8c45fSAndroid Build Coastguard Worker for (const InputTarget& inputTarget : inputTargets) {
2197*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<Connection> connection = inputTarget.connection;
2198*38e8c45fSAndroid Build Coastguard Worker prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);
2199*38e8c45fSAndroid Build Coastguard Worker }
2200*38e8c45fSAndroid Build Coastguard Worker }
2201*38e8c45fSAndroid Build Coastguard Worker
cancelEventsForAnrLocked(const std::shared_ptr<Connection> & connection)2202*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::cancelEventsForAnrLocked(const std::shared_ptr<Connection>& connection) {
2203*38e8c45fSAndroid Build Coastguard Worker // We will not be breaking any connections here, even if the policy wants us to abort dispatch.
2204*38e8c45fSAndroid Build Coastguard Worker // If the policy decides to close the app, we will get a channel removal event via
2205*38e8c45fSAndroid Build Coastguard Worker // unregisterInputChannel, and will clean up the connection that way. We are already not
2206*38e8c45fSAndroid Build Coastguard Worker // sending new pointers to the connection when it blocked, but focused events will continue to
2207*38e8c45fSAndroid Build Coastguard Worker // pile up.
2208*38e8c45fSAndroid Build Coastguard Worker ALOGW("Canceling events for %s because it is unresponsive",
2209*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str());
2210*38e8c45fSAndroid Build Coastguard Worker if (connection->status != Connection::Status::NORMAL) {
2211*38e8c45fSAndroid Build Coastguard Worker return;
2212*38e8c45fSAndroid Build Coastguard Worker }
2213*38e8c45fSAndroid Build Coastguard Worker ScopedSyntheticEventTracer traceContext(mTracer);
2214*38e8c45fSAndroid Build Coastguard Worker CancelationOptions options(CancelationOptions::Mode::CANCEL_ALL_EVENTS,
2215*38e8c45fSAndroid Build Coastguard Worker "application not responding", traceContext.getTracker());
2216*38e8c45fSAndroid Build Coastguard Worker
2217*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> windowHandle;
2218*38e8c45fSAndroid Build Coastguard Worker if (!connection->monitor) {
2219*38e8c45fSAndroid Build Coastguard Worker windowHandle = getWindowHandleLocked(connection->getToken());
2220*38e8c45fSAndroid Build Coastguard Worker if (windowHandle == nullptr) {
2221*38e8c45fSAndroid Build Coastguard Worker // The window that is receiving this ANR was removed, so there is no need to generate
2222*38e8c45fSAndroid Build Coastguard Worker // cancellations, because the cancellations would have already been generated when
2223*38e8c45fSAndroid Build Coastguard Worker // the window was removed.
2224*38e8c45fSAndroid Build Coastguard Worker return;
2225*38e8c45fSAndroid Build Coastguard Worker }
2226*38e8c45fSAndroid Build Coastguard Worker }
2227*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForConnectionLocked(connection, options, windowHandle);
2228*38e8c45fSAndroid Build Coastguard Worker }
2229*38e8c45fSAndroid Build Coastguard Worker
resetNoFocusedWindowTimeoutLocked()2230*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::resetNoFocusedWindowTimeoutLocked() {
2231*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_FOCUS) {
2232*38e8c45fSAndroid Build Coastguard Worker ALOGD("Resetting ANR timeouts.");
2233*38e8c45fSAndroid Build Coastguard Worker }
2234*38e8c45fSAndroid Build Coastguard Worker
2235*38e8c45fSAndroid Build Coastguard Worker // Reset input target wait timeout.
2236*38e8c45fSAndroid Build Coastguard Worker mNoFocusedWindowTimeoutTime = std::nullopt;
2237*38e8c45fSAndroid Build Coastguard Worker mAwaitedFocusedApplication.reset();
2238*38e8c45fSAndroid Build Coastguard Worker }
2239*38e8c45fSAndroid Build Coastguard Worker
2240*38e8c45fSAndroid Build Coastguard Worker /**
2241*38e8c45fSAndroid Build Coastguard Worker * Get the display id that the given event should go to. If this event specifies a valid display id,
2242*38e8c45fSAndroid Build Coastguard Worker * then it should be dispatched to that display. Otherwise, the event goes to the focused display.
2243*38e8c45fSAndroid Build Coastguard Worker * Focused display is the display that the user most recently interacted with.
2244*38e8c45fSAndroid Build Coastguard Worker */
getTargetDisplayId(const EventEntry & entry)2245*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId InputDispatcher::getTargetDisplayId(const EventEntry& entry) {
2246*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId displayId{ui::LogicalDisplayId::INVALID};
2247*38e8c45fSAndroid Build Coastguard Worker switch (entry.type) {
2248*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::KEY: {
2249*38e8c45fSAndroid Build Coastguard Worker const KeyEntry& keyEntry = static_cast<const KeyEntry&>(entry);
2250*38e8c45fSAndroid Build Coastguard Worker displayId = keyEntry.displayId;
2251*38e8c45fSAndroid Build Coastguard Worker break;
2252*38e8c45fSAndroid Build Coastguard Worker }
2253*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::MOTION: {
2254*38e8c45fSAndroid Build Coastguard Worker const MotionEntry& motionEntry = static_cast<const MotionEntry&>(entry);
2255*38e8c45fSAndroid Build Coastguard Worker displayId = motionEntry.displayId;
2256*38e8c45fSAndroid Build Coastguard Worker break;
2257*38e8c45fSAndroid Build Coastguard Worker }
2258*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::TOUCH_MODE_CHANGED:
2259*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::POINTER_CAPTURE_CHANGED:
2260*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::FOCUS:
2261*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::DEVICE_RESET:
2262*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::SENSOR:
2263*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::DRAG: {
2264*38e8c45fSAndroid Build Coastguard Worker ALOGE("%s events do not have a target display", ftl::enum_string(entry.type).c_str());
2265*38e8c45fSAndroid Build Coastguard Worker return ui::LogicalDisplayId::INVALID;
2266*38e8c45fSAndroid Build Coastguard Worker }
2267*38e8c45fSAndroid Build Coastguard Worker }
2268*38e8c45fSAndroid Build Coastguard Worker return displayId == ui::LogicalDisplayId::INVALID ? mFocusedDisplayId : displayId;
2269*38e8c45fSAndroid Build Coastguard Worker }
2270*38e8c45fSAndroid Build Coastguard Worker
shouldWaitToSendKeyLocked(nsecs_t currentTime,const char * focusedWindowName)2271*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::shouldWaitToSendKeyLocked(nsecs_t currentTime,
2272*38e8c45fSAndroid Build Coastguard Worker const char* focusedWindowName) {
2273*38e8c45fSAndroid Build Coastguard Worker if (mAnrTracker.empty()) {
2274*38e8c45fSAndroid Build Coastguard Worker // already processed all events that we waited for
2275*38e8c45fSAndroid Build Coastguard Worker mKeyIsWaitingForEventsTimeout = std::nullopt;
2276*38e8c45fSAndroid Build Coastguard Worker return false;
2277*38e8c45fSAndroid Build Coastguard Worker }
2278*38e8c45fSAndroid Build Coastguard Worker
2279*38e8c45fSAndroid Build Coastguard Worker if (!mKeyIsWaitingForEventsTimeout.has_value()) {
2280*38e8c45fSAndroid Build Coastguard Worker // Start the timer
2281*38e8c45fSAndroid Build Coastguard Worker // Wait to send key because there are unprocessed events that may cause focus to change
2282*38e8c45fSAndroid Build Coastguard Worker mKeyIsWaitingForEventsTimeout = currentTime +
2283*38e8c45fSAndroid Build Coastguard Worker std::chrono::duration_cast<std::chrono::nanoseconds>(
2284*38e8c45fSAndroid Build Coastguard Worker mPolicy.getKeyWaitingForEventsTimeout())
2285*38e8c45fSAndroid Build Coastguard Worker .count();
2286*38e8c45fSAndroid Build Coastguard Worker return true;
2287*38e8c45fSAndroid Build Coastguard Worker }
2288*38e8c45fSAndroid Build Coastguard Worker
2289*38e8c45fSAndroid Build Coastguard Worker // We still have pending events, and already started the timer
2290*38e8c45fSAndroid Build Coastguard Worker if (currentTime < *mKeyIsWaitingForEventsTimeout) {
2291*38e8c45fSAndroid Build Coastguard Worker return true; // Still waiting
2292*38e8c45fSAndroid Build Coastguard Worker }
2293*38e8c45fSAndroid Build Coastguard Worker
2294*38e8c45fSAndroid Build Coastguard Worker // Waited too long, and some connection still hasn't processed all motions
2295*38e8c45fSAndroid Build Coastguard Worker // Just send the key to the focused window
2296*38e8c45fSAndroid Build Coastguard Worker ALOGW("Dispatching key to %s even though there are other unprocessed events",
2297*38e8c45fSAndroid Build Coastguard Worker focusedWindowName);
2298*38e8c45fSAndroid Build Coastguard Worker mKeyIsWaitingForEventsTimeout = std::nullopt;
2299*38e8c45fSAndroid Build Coastguard Worker return false;
2300*38e8c45fSAndroid Build Coastguard Worker }
2301*38e8c45fSAndroid Build Coastguard Worker
2302*38e8c45fSAndroid Build Coastguard Worker Result<sp<WindowInfoHandle>, InputEventInjectionResult>
findFocusedWindowTargetLocked(nsecs_t currentTime,const EventEntry & entry,nsecs_t & nextWakeupTime)2303*38e8c45fSAndroid Build Coastguard Worker InputDispatcher::findFocusedWindowTargetLocked(nsecs_t currentTime, const EventEntry& entry,
2304*38e8c45fSAndroid Build Coastguard Worker nsecs_t& nextWakeupTime) {
2305*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId displayId = getTargetDisplayId(entry);
2306*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> focusedWindowHandle = getFocusedWindowHandleLocked(displayId);
2307*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<InputApplicationHandle> focusedApplicationHandle =
2308*38e8c45fSAndroid Build Coastguard Worker getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
2309*38e8c45fSAndroid Build Coastguard Worker
2310*38e8c45fSAndroid Build Coastguard Worker // If there is no currently focused window and no focused application
2311*38e8c45fSAndroid Build Coastguard Worker // then drop the event.
2312*38e8c45fSAndroid Build Coastguard Worker if (focusedWindowHandle == nullptr && focusedApplicationHandle == nullptr) {
2313*38e8c45fSAndroid Build Coastguard Worker ALOGI("Dropping %s event because there is no focused window or focused application in "
2314*38e8c45fSAndroid Build Coastguard Worker "display %s.",
2315*38e8c45fSAndroid Build Coastguard Worker ftl::enum_string(entry.type).c_str(), displayId.toString().c_str());
2316*38e8c45fSAndroid Build Coastguard Worker return injectionError(InputEventInjectionResult::FAILED);
2317*38e8c45fSAndroid Build Coastguard Worker }
2318*38e8c45fSAndroid Build Coastguard Worker
2319*38e8c45fSAndroid Build Coastguard Worker // Drop key events if requested by input feature
2320*38e8c45fSAndroid Build Coastguard Worker if (focusedWindowHandle != nullptr && shouldDropInput(entry, focusedWindowHandle)) {
2321*38e8c45fSAndroid Build Coastguard Worker return injectionError(InputEventInjectionResult::FAILED);
2322*38e8c45fSAndroid Build Coastguard Worker }
2323*38e8c45fSAndroid Build Coastguard Worker
2324*38e8c45fSAndroid Build Coastguard Worker // Compatibility behavior: raise ANR if there is a focused application, but no focused window.
2325*38e8c45fSAndroid Build Coastguard Worker // Only start counting when we have a focused event to dispatch. The ANR is canceled if we
2326*38e8c45fSAndroid Build Coastguard Worker // start interacting with another application via touch (app switch). This code can be removed
2327*38e8c45fSAndroid Build Coastguard Worker // if the "no focused window ANR" is moved to the policy. Input doesn't know whether
2328*38e8c45fSAndroid Build Coastguard Worker // an app is expected to have a focused window.
2329*38e8c45fSAndroid Build Coastguard Worker if (focusedWindowHandle == nullptr && focusedApplicationHandle != nullptr) {
2330*38e8c45fSAndroid Build Coastguard Worker if (!mNoFocusedWindowTimeoutTime.has_value()) {
2331*38e8c45fSAndroid Build Coastguard Worker // We just discovered that there's no focused window. Start the ANR timer
2332*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds timeout = focusedApplicationHandle->getDispatchingTimeout(
2333*38e8c45fSAndroid Build Coastguard Worker DEFAULT_INPUT_DISPATCHING_TIMEOUT);
2334*38e8c45fSAndroid Build Coastguard Worker mNoFocusedWindowTimeoutTime = currentTime + timeout.count();
2335*38e8c45fSAndroid Build Coastguard Worker mAwaitedFocusedApplication = focusedApplicationHandle;
2336*38e8c45fSAndroid Build Coastguard Worker mAwaitedApplicationDisplayId = displayId;
2337*38e8c45fSAndroid Build Coastguard Worker ALOGW("Waiting because no window has focus but %s may eventually add a "
2338*38e8c45fSAndroid Build Coastguard Worker "window when it finishes starting up. Will wait for %" PRId64 "ms",
2339*38e8c45fSAndroid Build Coastguard Worker mAwaitedFocusedApplication->getName().c_str(), millis(timeout));
2340*38e8c45fSAndroid Build Coastguard Worker nextWakeupTime = std::min(nextWakeupTime, *mNoFocusedWindowTimeoutTime);
2341*38e8c45fSAndroid Build Coastguard Worker return injectionError(InputEventInjectionResult::PENDING);
2342*38e8c45fSAndroid Build Coastguard Worker } else if (currentTime > *mNoFocusedWindowTimeoutTime) {
2343*38e8c45fSAndroid Build Coastguard Worker // Already raised ANR. Drop the event
2344*38e8c45fSAndroid Build Coastguard Worker ALOGE("Dropping %s event because there is no focused window",
2345*38e8c45fSAndroid Build Coastguard Worker ftl::enum_string(entry.type).c_str());
2346*38e8c45fSAndroid Build Coastguard Worker return injectionError(InputEventInjectionResult::FAILED);
2347*38e8c45fSAndroid Build Coastguard Worker } else {
2348*38e8c45fSAndroid Build Coastguard Worker // Still waiting for the focused window
2349*38e8c45fSAndroid Build Coastguard Worker return injectionError(InputEventInjectionResult::PENDING);
2350*38e8c45fSAndroid Build Coastguard Worker }
2351*38e8c45fSAndroid Build Coastguard Worker }
2352*38e8c45fSAndroid Build Coastguard Worker
2353*38e8c45fSAndroid Build Coastguard Worker // we have a valid, non-null focused window
2354*38e8c45fSAndroid Build Coastguard Worker resetNoFocusedWindowTimeoutLocked();
2355*38e8c45fSAndroid Build Coastguard Worker
2356*38e8c45fSAndroid Build Coastguard Worker // Verify targeted injection.
2357*38e8c45fSAndroid Build Coastguard Worker if (const auto err = verifyTargetedInjection(focusedWindowHandle, entry); err) {
2358*38e8c45fSAndroid Build Coastguard Worker ALOGW("Dropping injected event: %s", (*err).c_str());
2359*38e8c45fSAndroid Build Coastguard Worker return injectionError(InputEventInjectionResult::TARGET_MISMATCH);
2360*38e8c45fSAndroid Build Coastguard Worker }
2361*38e8c45fSAndroid Build Coastguard Worker
2362*38e8c45fSAndroid Build Coastguard Worker if (focusedWindowHandle->getInfo()->inputConfig.test(
2363*38e8c45fSAndroid Build Coastguard Worker WindowInfo::InputConfig::PAUSE_DISPATCHING)) {
2364*38e8c45fSAndroid Build Coastguard Worker ALOGI("Waiting because %s is paused", focusedWindowHandle->getName().c_str());
2365*38e8c45fSAndroid Build Coastguard Worker return injectionError(InputEventInjectionResult::PENDING);
2366*38e8c45fSAndroid Build Coastguard Worker }
2367*38e8c45fSAndroid Build Coastguard Worker
2368*38e8c45fSAndroid Build Coastguard Worker // If the event is a key event, then we must wait for all previous events to
2369*38e8c45fSAndroid Build Coastguard Worker // complete before delivering it because previous events may have the
2370*38e8c45fSAndroid Build Coastguard Worker // side-effect of transferring focus to a different window and we want to
2371*38e8c45fSAndroid Build Coastguard Worker // ensure that the following keys are sent to the new window.
2372*38e8c45fSAndroid Build Coastguard Worker //
2373*38e8c45fSAndroid Build Coastguard Worker // Suppose the user touches a button in a window then immediately presses "A".
2374*38e8c45fSAndroid Build Coastguard Worker // If the button causes a pop-up window to appear then we want to ensure that
2375*38e8c45fSAndroid Build Coastguard Worker // the "A" key is delivered to the new pop-up window. This is because users
2376*38e8c45fSAndroid Build Coastguard Worker // often anticipate pending UI changes when typing on a keyboard.
2377*38e8c45fSAndroid Build Coastguard Worker // To obtain this behavior, we must serialize key events with respect to all
2378*38e8c45fSAndroid Build Coastguard Worker // prior input events.
2379*38e8c45fSAndroid Build Coastguard Worker if (entry.type == EventEntry::Type::KEY) {
2380*38e8c45fSAndroid Build Coastguard Worker if (shouldWaitToSendKeyLocked(currentTime, focusedWindowHandle->getName().c_str())) {
2381*38e8c45fSAndroid Build Coastguard Worker nextWakeupTime = std::min(nextWakeupTime, *mKeyIsWaitingForEventsTimeout);
2382*38e8c45fSAndroid Build Coastguard Worker return injectionError(InputEventInjectionResult::PENDING);
2383*38e8c45fSAndroid Build Coastguard Worker }
2384*38e8c45fSAndroid Build Coastguard Worker }
2385*38e8c45fSAndroid Build Coastguard Worker // Success!
2386*38e8c45fSAndroid Build Coastguard Worker return focusedWindowHandle;
2387*38e8c45fSAndroid Build Coastguard Worker }
2388*38e8c45fSAndroid Build Coastguard Worker
2389*38e8c45fSAndroid Build Coastguard Worker /**
2390*38e8c45fSAndroid Build Coastguard Worker * Given a list of monitors, remove the ones we cannot find a connection for, and the ones
2391*38e8c45fSAndroid Build Coastguard Worker * that are currently unresponsive.
2392*38e8c45fSAndroid Build Coastguard Worker */
selectResponsiveMonitorsLocked(const std::vector<Monitor> & monitors) const2393*38e8c45fSAndroid Build Coastguard Worker std::vector<Monitor> InputDispatcher::selectResponsiveMonitorsLocked(
2394*38e8c45fSAndroid Build Coastguard Worker const std::vector<Monitor>& monitors) const {
2395*38e8c45fSAndroid Build Coastguard Worker std::vector<Monitor> responsiveMonitors;
2396*38e8c45fSAndroid Build Coastguard Worker std::copy_if(monitors.begin(), monitors.end(), std::back_inserter(responsiveMonitors),
2397*38e8c45fSAndroid Build Coastguard Worker [](const Monitor& monitor) REQUIRES(mLock) {
2398*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<Connection> connection = monitor.connection;
2399*38e8c45fSAndroid Build Coastguard Worker if (!connection->responsive) {
2400*38e8c45fSAndroid Build Coastguard Worker ALOGW("Unresponsive monitor %s will not get the new gesture",
2401*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str());
2402*38e8c45fSAndroid Build Coastguard Worker return false;
2403*38e8c45fSAndroid Build Coastguard Worker }
2404*38e8c45fSAndroid Build Coastguard Worker return true;
2405*38e8c45fSAndroid Build Coastguard Worker });
2406*38e8c45fSAndroid Build Coastguard Worker return responsiveMonitors;
2407*38e8c45fSAndroid Build Coastguard Worker }
2408*38e8c45fSAndroid Build Coastguard Worker
2409*38e8c45fSAndroid Build Coastguard Worker base::Result<std::vector<InputTarget>, android::os::InputEventInjectionResult>
findTouchedWindowTargetsLocked(nsecs_t currentTime,const MotionEntry & entry)2410*38e8c45fSAndroid Build Coastguard Worker InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry& entry) {
2411*38e8c45fSAndroid Build Coastguard Worker ATRACE_CALL();
2412*38e8c45fSAndroid Build Coastguard Worker
2413*38e8c45fSAndroid Build Coastguard Worker std::vector<InputTarget> targets;
2414*38e8c45fSAndroid Build Coastguard Worker // For security reasons, we defer updating the touch state until we are sure that
2415*38e8c45fSAndroid Build Coastguard Worker // event injection will be allowed.
2416*38e8c45fSAndroid Build Coastguard Worker const ui::LogicalDisplayId displayId = entry.displayId;
2417*38e8c45fSAndroid Build Coastguard Worker const int32_t action = entry.action;
2418*38e8c45fSAndroid Build Coastguard Worker const int32_t maskedAction = MotionEvent::getActionMasked(action);
2419*38e8c45fSAndroid Build Coastguard Worker
2420*38e8c45fSAndroid Build Coastguard Worker // Copy current touch state into tempTouchState.
2421*38e8c45fSAndroid Build Coastguard Worker // This state will be used to update mTouchStatesByDisplay at the end of this function.
2422*38e8c45fSAndroid Build Coastguard Worker // If no state for the specified display exists, then our initial state will be empty.
2423*38e8c45fSAndroid Build Coastguard Worker const TouchState* oldState = nullptr;
2424*38e8c45fSAndroid Build Coastguard Worker TouchState tempTouchState;
2425*38e8c45fSAndroid Build Coastguard Worker if (const auto it = mTouchStatesByDisplay.find(displayId); it != mTouchStatesByDisplay.end()) {
2426*38e8c45fSAndroid Build Coastguard Worker oldState = &(it->second);
2427*38e8c45fSAndroid Build Coastguard Worker tempTouchState = *oldState;
2428*38e8c45fSAndroid Build Coastguard Worker }
2429*38e8c45fSAndroid Build Coastguard Worker
2430*38e8c45fSAndroid Build Coastguard Worker bool isSplit = shouldSplitTouch(tempTouchState, entry);
2431*38e8c45fSAndroid Build Coastguard Worker
2432*38e8c45fSAndroid Build Coastguard Worker const bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE ||
2433*38e8c45fSAndroid Build Coastguard Worker maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
2434*38e8c45fSAndroid Build Coastguard Worker maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT);
2435*38e8c45fSAndroid Build Coastguard Worker // A DOWN could be generated from POINTER_DOWN if the initial pointers did not land into any
2436*38e8c45fSAndroid Build Coastguard Worker // touchable windows.
2437*38e8c45fSAndroid Build Coastguard Worker const bool wasDown = oldState != nullptr && oldState->isDown(entry.deviceId);
2438*38e8c45fSAndroid Build Coastguard Worker const bool isDown = (maskedAction == AMOTION_EVENT_ACTION_DOWN) ||
2439*38e8c45fSAndroid Build Coastguard Worker (maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN && !wasDown);
2440*38e8c45fSAndroid Build Coastguard Worker const bool newGesture = isDown || maskedAction == AMOTION_EVENT_ACTION_SCROLL ||
2441*38e8c45fSAndroid Build Coastguard Worker maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
2442*38e8c45fSAndroid Build Coastguard Worker maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE;
2443*38e8c45fSAndroid Build Coastguard Worker const bool isFromMouse = isFromSource(entry.source, AINPUT_SOURCE_MOUSE);
2444*38e8c45fSAndroid Build Coastguard Worker
2445*38e8c45fSAndroid Build Coastguard Worker if (newGesture) {
2446*38e8c45fSAndroid Build Coastguard Worker isSplit = false;
2447*38e8c45fSAndroid Build Coastguard Worker }
2448*38e8c45fSAndroid Build Coastguard Worker
2449*38e8c45fSAndroid Build Coastguard Worker if (isDown && tempTouchState.hasHoveringPointers(entry.deviceId)) {
2450*38e8c45fSAndroid Build Coastguard Worker // Compatibility behaviour: ACTION_DOWN causes HOVER_EXIT to get generated.
2451*38e8c45fSAndroid Build Coastguard Worker tempTouchState.clearHoveringPointers(entry.deviceId);
2452*38e8c45fSAndroid Build Coastguard Worker }
2453*38e8c45fSAndroid Build Coastguard Worker
2454*38e8c45fSAndroid Build Coastguard Worker if (isHoverAction) {
2455*38e8c45fSAndroid Build Coastguard Worker if (wasDown) {
2456*38e8c45fSAndroid Build Coastguard Worker // Started hovering, but the device is already down: reject the hover event
2457*38e8c45fSAndroid Build Coastguard Worker LOG(ERROR) << "Got hover event " << entry.getDescription()
2458*38e8c45fSAndroid Build Coastguard Worker << " but the device is already down " << oldState->dump();
2459*38e8c45fSAndroid Build Coastguard Worker return injectionError(InputEventInjectionResult::FAILED);
2460*38e8c45fSAndroid Build Coastguard Worker }
2461*38e8c45fSAndroid Build Coastguard Worker // For hover actions, we will treat 'tempTouchState' as a new state, so let's erase
2462*38e8c45fSAndroid Build Coastguard Worker // all of the existing hovering pointers and recompute.
2463*38e8c45fSAndroid Build Coastguard Worker tempTouchState.clearHoveringPointers(entry.deviceId);
2464*38e8c45fSAndroid Build Coastguard Worker }
2465*38e8c45fSAndroid Build Coastguard Worker
2466*38e8c45fSAndroid Build Coastguard Worker if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
2467*38e8c45fSAndroid Build Coastguard Worker /* Case 1: New splittable pointer going down, or need target for hover or scroll. */
2468*38e8c45fSAndroid Build Coastguard Worker const auto [x, y] = resolveTouchedPosition(entry);
2469*38e8c45fSAndroid Build Coastguard Worker const int32_t pointerIndex = MotionEvent::getActionIndex(action);
2470*38e8c45fSAndroid Build Coastguard Worker const PointerProperties& pointer = entry.pointerProperties[pointerIndex];
2471*38e8c45fSAndroid Build Coastguard Worker // Outside targets should be added upon first dispatched DOWN event. That means, this should
2472*38e8c45fSAndroid Build Coastguard Worker // be a pointer that would generate ACTION_DOWN, *and* touch should not already be down.
2473*38e8c45fSAndroid Build Coastguard Worker const bool isStylus = isPointerFromStylus(entry, pointerIndex);
2474*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> newTouchedWindowHandle =
2475*38e8c45fSAndroid Build Coastguard Worker findTouchedWindowAtLocked(displayId, x, y, isStylus);
2476*38e8c45fSAndroid Build Coastguard Worker
2477*38e8c45fSAndroid Build Coastguard Worker if (isDown) {
2478*38e8c45fSAndroid Build Coastguard Worker targets += findOutsideTargetsLocked(displayId, newTouchedWindowHandle, pointer.id);
2479*38e8c45fSAndroid Build Coastguard Worker }
2480*38e8c45fSAndroid Build Coastguard Worker LOG_IF(INFO, newTouchedWindowHandle == nullptr)
2481*38e8c45fSAndroid Build Coastguard Worker << "No new touched window at (" << std::format("{:.1f}, {:.1f}", x, y)
2482*38e8c45fSAndroid Build Coastguard Worker << ") in display " << displayId;
2483*38e8c45fSAndroid Build Coastguard Worker // Handle the case where we did not find a window.
2484*38e8c45fSAndroid Build Coastguard Worker if (!input_flags::split_all_touches()) {
2485*38e8c45fSAndroid Build Coastguard Worker // If we are force splitting all touches, then touches outside of the window should
2486*38e8c45fSAndroid Build Coastguard Worker // be dropped, even if this device already has pointers down in another window.
2487*38e8c45fSAndroid Build Coastguard Worker if (newTouchedWindowHandle == nullptr) {
2488*38e8c45fSAndroid Build Coastguard Worker // Try to assign the pointer to the first foreground window we find, if there is
2489*38e8c45fSAndroid Build Coastguard Worker // one.
2490*38e8c45fSAndroid Build Coastguard Worker newTouchedWindowHandle =
2491*38e8c45fSAndroid Build Coastguard Worker tempTouchState.getFirstForegroundWindowHandle(entry.deviceId);
2492*38e8c45fSAndroid Build Coastguard Worker }
2493*38e8c45fSAndroid Build Coastguard Worker }
2494*38e8c45fSAndroid Build Coastguard Worker
2495*38e8c45fSAndroid Build Coastguard Worker // Verify targeted injection.
2496*38e8c45fSAndroid Build Coastguard Worker if (const auto err = verifyTargetedInjection(newTouchedWindowHandle, entry); err) {
2497*38e8c45fSAndroid Build Coastguard Worker ALOGW("Dropping injected touch event: %s", (*err).c_str());
2498*38e8c45fSAndroid Build Coastguard Worker return injectionError(InputEventInjectionResult::TARGET_MISMATCH);
2499*38e8c45fSAndroid Build Coastguard Worker }
2500*38e8c45fSAndroid Build Coastguard Worker
2501*38e8c45fSAndroid Build Coastguard Worker // Figure out whether splitting will be allowed for this window.
2502*38e8c45fSAndroid Build Coastguard Worker if (newTouchedWindowHandle != nullptr) {
2503*38e8c45fSAndroid Build Coastguard Worker if (newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
2504*38e8c45fSAndroid Build Coastguard Worker // New window supports splitting, but we should never split mouse events.
2505*38e8c45fSAndroid Build Coastguard Worker isSplit = !isFromMouse;
2506*38e8c45fSAndroid Build Coastguard Worker } else if (isSplit) {
2507*38e8c45fSAndroid Build Coastguard Worker // New window does not support splitting but we have already split events.
2508*38e8c45fSAndroid Build Coastguard Worker // Ignore the new window.
2509*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "Skipping " << newTouchedWindowHandle->getName()
2510*38e8c45fSAndroid Build Coastguard Worker << " because it doesn't support split touch";
2511*38e8c45fSAndroid Build Coastguard Worker newTouchedWindowHandle = nullptr;
2512*38e8c45fSAndroid Build Coastguard Worker }
2513*38e8c45fSAndroid Build Coastguard Worker } else {
2514*38e8c45fSAndroid Build Coastguard Worker // No window is touched, so set split to true. This will allow the next pointer down to
2515*38e8c45fSAndroid Build Coastguard Worker // be delivered to a new window which supports split touch. Pointers from a mouse device
2516*38e8c45fSAndroid Build Coastguard Worker // should never be split.
2517*38e8c45fSAndroid Build Coastguard Worker isSplit = !isFromMouse;
2518*38e8c45fSAndroid Build Coastguard Worker }
2519*38e8c45fSAndroid Build Coastguard Worker
2520*38e8c45fSAndroid Build Coastguard Worker std::vector<sp<WindowInfoHandle>> newTouchedWindows =
2521*38e8c45fSAndroid Build Coastguard Worker findTouchedSpyWindowsAtLocked(displayId, x, y, isStylus, entry.deviceId);
2522*38e8c45fSAndroid Build Coastguard Worker if (newTouchedWindowHandle != nullptr) {
2523*38e8c45fSAndroid Build Coastguard Worker // Process the foreground window first so that it is the first to receive the event.
2524*38e8c45fSAndroid Build Coastguard Worker newTouchedWindows.insert(newTouchedWindows.begin(), newTouchedWindowHandle);
2525*38e8c45fSAndroid Build Coastguard Worker }
2526*38e8c45fSAndroid Build Coastguard Worker
2527*38e8c45fSAndroid Build Coastguard Worker if (newTouchedWindows.empty()) {
2528*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "Dropping event because there is no touchable window at (" << x << ", "
2529*38e8c45fSAndroid Build Coastguard Worker << y << ") on display " << displayId << ": " << entry;
2530*38e8c45fSAndroid Build Coastguard Worker return injectionError(InputEventInjectionResult::FAILED);
2531*38e8c45fSAndroid Build Coastguard Worker }
2532*38e8c45fSAndroid Build Coastguard Worker
2533*38e8c45fSAndroid Build Coastguard Worker for (const sp<WindowInfoHandle>& windowHandle : newTouchedWindows) {
2534*38e8c45fSAndroid Build Coastguard Worker if (!canWindowReceiveMotionLocked(windowHandle, entry)) {
2535*38e8c45fSAndroid Build Coastguard Worker continue;
2536*38e8c45fSAndroid Build Coastguard Worker }
2537*38e8c45fSAndroid Build Coastguard Worker
2538*38e8c45fSAndroid Build Coastguard Worker if (isHoverAction) {
2539*38e8c45fSAndroid Build Coastguard Worker // The "windowHandle" is the target of this hovering pointer.
2540*38e8c45fSAndroid Build Coastguard Worker tempTouchState.addHoveringPointerToWindow(windowHandle, entry.deviceId, pointer, x,
2541*38e8c45fSAndroid Build Coastguard Worker y);
2542*38e8c45fSAndroid Build Coastguard Worker }
2543*38e8c45fSAndroid Build Coastguard Worker
2544*38e8c45fSAndroid Build Coastguard Worker // Set target flags.
2545*38e8c45fSAndroid Build Coastguard Worker ftl::Flags<InputTarget::Flags> targetFlags;
2546*38e8c45fSAndroid Build Coastguard Worker
2547*38e8c45fSAndroid Build Coastguard Worker if (canReceiveForegroundTouches(*windowHandle->getInfo())) {
2548*38e8c45fSAndroid Build Coastguard Worker // There should only be one touched window that can be "foreground" for the pointer.
2549*38e8c45fSAndroid Build Coastguard Worker targetFlags |= InputTarget::Flags::FOREGROUND;
2550*38e8c45fSAndroid Build Coastguard Worker }
2551*38e8c45fSAndroid Build Coastguard Worker
2552*38e8c45fSAndroid Build Coastguard Worker if (isSplit) {
2553*38e8c45fSAndroid Build Coastguard Worker targetFlags |= InputTarget::Flags::SPLIT;
2554*38e8c45fSAndroid Build Coastguard Worker }
2555*38e8c45fSAndroid Build Coastguard Worker if (isWindowObscuredAtPointLocked(windowHandle, x, y)) {
2556*38e8c45fSAndroid Build Coastguard Worker targetFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED;
2557*38e8c45fSAndroid Build Coastguard Worker } else if (isWindowObscuredLocked(windowHandle)) {
2558*38e8c45fSAndroid Build Coastguard Worker targetFlags |= InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
2559*38e8c45fSAndroid Build Coastguard Worker }
2560*38e8c45fSAndroid Build Coastguard Worker
2561*38e8c45fSAndroid Build Coastguard Worker // Update the temporary touch state.
2562*38e8c45fSAndroid Build Coastguard Worker
2563*38e8c45fSAndroid Build Coastguard Worker if (!isHoverAction) {
2564*38e8c45fSAndroid Build Coastguard Worker const bool isDownOrPointerDown = maskedAction == AMOTION_EVENT_ACTION_DOWN ||
2565*38e8c45fSAndroid Build Coastguard Worker maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN;
2566*38e8c45fSAndroid Build Coastguard Worker Result<void> addResult =
2567*38e8c45fSAndroid Build Coastguard Worker tempTouchState.addOrUpdateWindow(windowHandle,
2568*38e8c45fSAndroid Build Coastguard Worker InputTarget::DispatchMode::AS_IS,
2569*38e8c45fSAndroid Build Coastguard Worker targetFlags, entry.deviceId, {pointer},
2570*38e8c45fSAndroid Build Coastguard Worker isDownOrPointerDown
2571*38e8c45fSAndroid Build Coastguard Worker ? std::make_optional(
2572*38e8c45fSAndroid Build Coastguard Worker entry.eventTime)
2573*38e8c45fSAndroid Build Coastguard Worker : std::nullopt);
2574*38e8c45fSAndroid Build Coastguard Worker if (!addResult.ok()) {
2575*38e8c45fSAndroid Build Coastguard Worker LOG(ERROR) << "Error while processing " << entry << " for "
2576*38e8c45fSAndroid Build Coastguard Worker << windowHandle->getName();
2577*38e8c45fSAndroid Build Coastguard Worker logDispatchStateLocked();
2578*38e8c45fSAndroid Build Coastguard Worker }
2579*38e8c45fSAndroid Build Coastguard Worker // If this is the pointer going down and the touched window has a wallpaper
2580*38e8c45fSAndroid Build Coastguard Worker // then also add the touched wallpaper windows so they are locked in for the
2581*38e8c45fSAndroid Build Coastguard Worker // duration of the touch gesture. We do not collect wallpapers during HOVER_MOVE or
2582*38e8c45fSAndroid Build Coastguard Worker // SCROLL because the wallpaper engine only supports touch events. We would need to
2583*38e8c45fSAndroid Build Coastguard Worker // add a mechanism similar to View.onGenericMotionEvent to enable wallpapers to
2584*38e8c45fSAndroid Build Coastguard Worker // handle these events.
2585*38e8c45fSAndroid Build Coastguard Worker if (isDownOrPointerDown && targetFlags.test(InputTarget::Flags::FOREGROUND) &&
2586*38e8c45fSAndroid Build Coastguard Worker windowHandle->getInfo()->inputConfig.test(
2587*38e8c45fSAndroid Build Coastguard Worker gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
2588*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> wallpaper = findWallpaperWindowBelow(windowHandle);
2589*38e8c45fSAndroid Build Coastguard Worker if (wallpaper != nullptr) {
2590*38e8c45fSAndroid Build Coastguard Worker ftl::Flags<InputTarget::Flags> wallpaperFlags =
2591*38e8c45fSAndroid Build Coastguard Worker InputTarget::Flags::WINDOW_IS_OBSCURED |
2592*38e8c45fSAndroid Build Coastguard Worker InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
2593*38e8c45fSAndroid Build Coastguard Worker if (isSplit) {
2594*38e8c45fSAndroid Build Coastguard Worker wallpaperFlags |= InputTarget::Flags::SPLIT;
2595*38e8c45fSAndroid Build Coastguard Worker }
2596*38e8c45fSAndroid Build Coastguard Worker tempTouchState.addOrUpdateWindow(wallpaper,
2597*38e8c45fSAndroid Build Coastguard Worker InputTarget::DispatchMode::AS_IS,
2598*38e8c45fSAndroid Build Coastguard Worker wallpaperFlags, entry.deviceId, {pointer},
2599*38e8c45fSAndroid Build Coastguard Worker entry.eventTime);
2600*38e8c45fSAndroid Build Coastguard Worker }
2601*38e8c45fSAndroid Build Coastguard Worker }
2602*38e8c45fSAndroid Build Coastguard Worker }
2603*38e8c45fSAndroid Build Coastguard Worker }
2604*38e8c45fSAndroid Build Coastguard Worker
2605*38e8c45fSAndroid Build Coastguard Worker // If a window is already pilfering some pointers, give it this new pointer as well and
2606*38e8c45fSAndroid Build Coastguard Worker // make it pilfering. This will prevent other non-spy windows from getting this pointer,
2607*38e8c45fSAndroid Build Coastguard Worker // which is a specific behaviour that we want.
2608*38e8c45fSAndroid Build Coastguard Worker for (TouchedWindow& touchedWindow : tempTouchState.windows) {
2609*38e8c45fSAndroid Build Coastguard Worker if (touchedWindow.hasTouchingPointer(entry.deviceId, pointer.id) &&
2610*38e8c45fSAndroid Build Coastguard Worker touchedWindow.hasPilferingPointers(entry.deviceId)) {
2611*38e8c45fSAndroid Build Coastguard Worker // This window is already pilfering some pointers, and this new pointer is also
2612*38e8c45fSAndroid Build Coastguard Worker // going to it. Therefore, take over this pointer and don't give it to anyone
2613*38e8c45fSAndroid Build Coastguard Worker // else.
2614*38e8c45fSAndroid Build Coastguard Worker touchedWindow.addPilferingPointer(entry.deviceId, pointer.id);
2615*38e8c45fSAndroid Build Coastguard Worker }
2616*38e8c45fSAndroid Build Coastguard Worker }
2617*38e8c45fSAndroid Build Coastguard Worker
2618*38e8c45fSAndroid Build Coastguard Worker // Restrict all pilfered pointers to the pilfering windows.
2619*38e8c45fSAndroid Build Coastguard Worker tempTouchState.cancelPointersForNonPilferingWindows();
2620*38e8c45fSAndroid Build Coastguard Worker } else {
2621*38e8c45fSAndroid Build Coastguard Worker /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */
2622*38e8c45fSAndroid Build Coastguard Worker
2623*38e8c45fSAndroid Build Coastguard Worker // If the pointer is not currently down, then ignore the event.
2624*38e8c45fSAndroid Build Coastguard Worker if (!tempTouchState.isDown(entry.deviceId) &&
2625*38e8c45fSAndroid Build Coastguard Worker maskedAction != AMOTION_EVENT_ACTION_HOVER_EXIT) {
2626*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_DROPPED_EVENTS_VERBOSE) {
2627*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "Dropping event because the pointer for device " << entry.deviceId
2628*38e8c45fSAndroid Build Coastguard Worker << " is not down or we previously dropped the pointer down event in "
2629*38e8c45fSAndroid Build Coastguard Worker << "display " << displayId << ": " << entry.getDescription();
2630*38e8c45fSAndroid Build Coastguard Worker }
2631*38e8c45fSAndroid Build Coastguard Worker return injectionError(InputEventInjectionResult::FAILED);
2632*38e8c45fSAndroid Build Coastguard Worker }
2633*38e8c45fSAndroid Build Coastguard Worker
2634*38e8c45fSAndroid Build Coastguard Worker // If the pointer is not currently hovering, then ignore the event.
2635*38e8c45fSAndroid Build Coastguard Worker if (maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT) {
2636*38e8c45fSAndroid Build Coastguard Worker const int32_t pointerId = entry.pointerProperties[0].id;
2637*38e8c45fSAndroid Build Coastguard Worker if (oldState == nullptr ||
2638*38e8c45fSAndroid Build Coastguard Worker oldState->getWindowsWithHoveringPointer(entry.deviceId, pointerId).empty()) {
2639*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "Dropping event because the hovering pointer is not in any windows in "
2640*38e8c45fSAndroid Build Coastguard Worker "display "
2641*38e8c45fSAndroid Build Coastguard Worker << displayId << ": " << entry.getDescription();
2642*38e8c45fSAndroid Build Coastguard Worker return injectionError(InputEventInjectionResult::FAILED);
2643*38e8c45fSAndroid Build Coastguard Worker }
2644*38e8c45fSAndroid Build Coastguard Worker tempTouchState.removeHoveringPointer(entry.deviceId, pointerId);
2645*38e8c45fSAndroid Build Coastguard Worker }
2646*38e8c45fSAndroid Build Coastguard Worker
2647*38e8c45fSAndroid Build Coastguard Worker addDragEventLocked(entry);
2648*38e8c45fSAndroid Build Coastguard Worker
2649*38e8c45fSAndroid Build Coastguard Worker // Check whether touches should slip outside of the current foreground window.
2650*38e8c45fSAndroid Build Coastguard Worker if (maskedAction == AMOTION_EVENT_ACTION_MOVE && entry.getPointerCount() == 1 &&
2651*38e8c45fSAndroid Build Coastguard Worker tempTouchState.isSlippery(entry.deviceId)) {
2652*38e8c45fSAndroid Build Coastguard Worker const auto [x, y] = resolveTouchedPosition(entry);
2653*38e8c45fSAndroid Build Coastguard Worker const bool isStylus = isPointerFromStylus(entry, /*pointerIndex=*/0);
2654*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> oldTouchedWindowHandle =
2655*38e8c45fSAndroid Build Coastguard Worker tempTouchState.getFirstForegroundWindowHandle(entry.deviceId);
2656*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(oldTouchedWindowHandle == nullptr);
2657*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> newTouchedWindowHandle =
2658*38e8c45fSAndroid Build Coastguard Worker findTouchedWindowAtLocked(displayId, x, y, isStylus);
2659*38e8c45fSAndroid Build Coastguard Worker
2660*38e8c45fSAndroid Build Coastguard Worker // Verify targeted injection.
2661*38e8c45fSAndroid Build Coastguard Worker if (const auto err = verifyTargetedInjection(newTouchedWindowHandle, entry); err) {
2662*38e8c45fSAndroid Build Coastguard Worker ALOGW("Dropping injected event: %s", (*err).c_str());
2663*38e8c45fSAndroid Build Coastguard Worker return injectionError(InputEventInjectionResult::TARGET_MISMATCH);
2664*38e8c45fSAndroid Build Coastguard Worker }
2665*38e8c45fSAndroid Build Coastguard Worker
2666*38e8c45fSAndroid Build Coastguard Worker // Do not slide events to the window which can not receive motion event
2667*38e8c45fSAndroid Build Coastguard Worker if (newTouchedWindowHandle != nullptr &&
2668*38e8c45fSAndroid Build Coastguard Worker !canWindowReceiveMotionLocked(newTouchedWindowHandle, entry)) {
2669*38e8c45fSAndroid Build Coastguard Worker newTouchedWindowHandle = nullptr;
2670*38e8c45fSAndroid Build Coastguard Worker }
2671*38e8c45fSAndroid Build Coastguard Worker
2672*38e8c45fSAndroid Build Coastguard Worker if (newTouchedWindowHandle != nullptr &&
2673*38e8c45fSAndroid Build Coastguard Worker !haveSameToken(oldTouchedWindowHandle, newTouchedWindowHandle)) {
2674*38e8c45fSAndroid Build Coastguard Worker ALOGI("Touch is slipping out of window %s into window %s in display %s",
2675*38e8c45fSAndroid Build Coastguard Worker oldTouchedWindowHandle->getName().c_str(),
2676*38e8c45fSAndroid Build Coastguard Worker newTouchedWindowHandle->getName().c_str(), displayId.toString().c_str());
2677*38e8c45fSAndroid Build Coastguard Worker
2678*38e8c45fSAndroid Build Coastguard Worker // Make a slippery exit from the old window.
2679*38e8c45fSAndroid Build Coastguard Worker std::bitset<MAX_POINTER_ID + 1> pointerIds;
2680*38e8c45fSAndroid Build Coastguard Worker const PointerProperties& pointer = entry.pointerProperties[0];
2681*38e8c45fSAndroid Build Coastguard Worker pointerIds.set(pointer.id);
2682*38e8c45fSAndroid Build Coastguard Worker
2683*38e8c45fSAndroid Build Coastguard Worker const TouchedWindow& touchedWindow =
2684*38e8c45fSAndroid Build Coastguard Worker tempTouchState.getTouchedWindow(oldTouchedWindowHandle);
2685*38e8c45fSAndroid Build Coastguard Worker addPointerWindowTargetLocked(oldTouchedWindowHandle,
2686*38e8c45fSAndroid Build Coastguard Worker InputTarget::DispatchMode::SLIPPERY_EXIT,
2687*38e8c45fSAndroid Build Coastguard Worker ftl::Flags<InputTarget::Flags>(), pointerIds,
2688*38e8c45fSAndroid Build Coastguard Worker touchedWindow.getDownTimeInTarget(entry.deviceId),
2689*38e8c45fSAndroid Build Coastguard Worker targets);
2690*38e8c45fSAndroid Build Coastguard Worker
2691*38e8c45fSAndroid Build Coastguard Worker // Make a slippery entrance into the new window.
2692*38e8c45fSAndroid Build Coastguard Worker if (newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
2693*38e8c45fSAndroid Build Coastguard Worker isSplit = !isFromMouse;
2694*38e8c45fSAndroid Build Coastguard Worker }
2695*38e8c45fSAndroid Build Coastguard Worker
2696*38e8c45fSAndroid Build Coastguard Worker ftl::Flags<InputTarget::Flags> targetFlags;
2697*38e8c45fSAndroid Build Coastguard Worker if (canReceiveForegroundTouches(*newTouchedWindowHandle->getInfo())) {
2698*38e8c45fSAndroid Build Coastguard Worker targetFlags |= InputTarget::Flags::FOREGROUND;
2699*38e8c45fSAndroid Build Coastguard Worker }
2700*38e8c45fSAndroid Build Coastguard Worker if (isSplit) {
2701*38e8c45fSAndroid Build Coastguard Worker targetFlags |= InputTarget::Flags::SPLIT;
2702*38e8c45fSAndroid Build Coastguard Worker }
2703*38e8c45fSAndroid Build Coastguard Worker if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
2704*38e8c45fSAndroid Build Coastguard Worker targetFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED;
2705*38e8c45fSAndroid Build Coastguard Worker } else if (isWindowObscuredLocked(newTouchedWindowHandle)) {
2706*38e8c45fSAndroid Build Coastguard Worker targetFlags |= InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
2707*38e8c45fSAndroid Build Coastguard Worker }
2708*38e8c45fSAndroid Build Coastguard Worker
2709*38e8c45fSAndroid Build Coastguard Worker tempTouchState.addOrUpdateWindow(newTouchedWindowHandle,
2710*38e8c45fSAndroid Build Coastguard Worker InputTarget::DispatchMode::SLIPPERY_ENTER,
2711*38e8c45fSAndroid Build Coastguard Worker targetFlags, entry.deviceId, {pointer},
2712*38e8c45fSAndroid Build Coastguard Worker entry.eventTime);
2713*38e8c45fSAndroid Build Coastguard Worker
2714*38e8c45fSAndroid Build Coastguard Worker // Check if the wallpaper window should deliver the corresponding event.
2715*38e8c45fSAndroid Build Coastguard Worker slipWallpaperTouch(targetFlags, oldTouchedWindowHandle, newTouchedWindowHandle,
2716*38e8c45fSAndroid Build Coastguard Worker tempTouchState, entry, targets);
2717*38e8c45fSAndroid Build Coastguard Worker tempTouchState.removeTouchingPointerFromWindow(entry.deviceId, pointer.id,
2718*38e8c45fSAndroid Build Coastguard Worker oldTouchedWindowHandle);
2719*38e8c45fSAndroid Build Coastguard Worker }
2720*38e8c45fSAndroid Build Coastguard Worker }
2721*38e8c45fSAndroid Build Coastguard Worker
2722*38e8c45fSAndroid Build Coastguard Worker // Update the pointerIds for non-splittable when it received pointer down.
2723*38e8c45fSAndroid Build Coastguard Worker if (!isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN) {
2724*38e8c45fSAndroid Build Coastguard Worker // If no split, we suppose all touched windows should receive pointer down.
2725*38e8c45fSAndroid Build Coastguard Worker const int32_t pointerIndex = MotionEvent::getActionIndex(action);
2726*38e8c45fSAndroid Build Coastguard Worker std::vector<PointerProperties> touchingPointers{entry.pointerProperties[pointerIndex]};
2727*38e8c45fSAndroid Build Coastguard Worker for (TouchedWindow& touchedWindow : tempTouchState.windows) {
2728*38e8c45fSAndroid Build Coastguard Worker // Ignore drag window for it should just track one pointer.
2729*38e8c45fSAndroid Build Coastguard Worker if (mDragState && mDragState->dragWindow == touchedWindow.windowHandle) {
2730*38e8c45fSAndroid Build Coastguard Worker continue;
2731*38e8c45fSAndroid Build Coastguard Worker }
2732*38e8c45fSAndroid Build Coastguard Worker if (!touchedWindow.hasTouchingPointers(entry.deviceId)) {
2733*38e8c45fSAndroid Build Coastguard Worker continue;
2734*38e8c45fSAndroid Build Coastguard Worker }
2735*38e8c45fSAndroid Build Coastguard Worker touchedWindow.addTouchingPointers(entry.deviceId, touchingPointers);
2736*38e8c45fSAndroid Build Coastguard Worker }
2737*38e8c45fSAndroid Build Coastguard Worker }
2738*38e8c45fSAndroid Build Coastguard Worker }
2739*38e8c45fSAndroid Build Coastguard Worker
2740*38e8c45fSAndroid Build Coastguard Worker // Update dispatching for hover enter and exit.
2741*38e8c45fSAndroid Build Coastguard Worker {
2742*38e8c45fSAndroid Build Coastguard Worker std::vector<TouchedWindow> hoveringWindows =
2743*38e8c45fSAndroid Build Coastguard Worker getHoveringWindowsLocked(oldState, tempTouchState, entry,
2744*38e8c45fSAndroid Build Coastguard Worker std::bind_front(&InputDispatcher::logDispatchStateLocked,
2745*38e8c45fSAndroid Build Coastguard Worker this));
2746*38e8c45fSAndroid Build Coastguard Worker // Hardcode to single hovering pointer for now.
2747*38e8c45fSAndroid Build Coastguard Worker std::bitset<MAX_POINTER_ID + 1> pointerIds;
2748*38e8c45fSAndroid Build Coastguard Worker pointerIds.set(entry.pointerProperties[0].id);
2749*38e8c45fSAndroid Build Coastguard Worker for (const TouchedWindow& touchedWindow : hoveringWindows) {
2750*38e8c45fSAndroid Build Coastguard Worker addPointerWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.dispatchMode,
2751*38e8c45fSAndroid Build Coastguard Worker touchedWindow.targetFlags, pointerIds,
2752*38e8c45fSAndroid Build Coastguard Worker touchedWindow.getDownTimeInTarget(entry.deviceId),
2753*38e8c45fSAndroid Build Coastguard Worker targets);
2754*38e8c45fSAndroid Build Coastguard Worker }
2755*38e8c45fSAndroid Build Coastguard Worker }
2756*38e8c45fSAndroid Build Coastguard Worker
2757*38e8c45fSAndroid Build Coastguard Worker // Ensure that all touched windows are valid for injection.
2758*38e8c45fSAndroid Build Coastguard Worker if (entry.injectionState != nullptr) {
2759*38e8c45fSAndroid Build Coastguard Worker std::string errs;
2760*38e8c45fSAndroid Build Coastguard Worker for (const TouchedWindow& touchedWindow : tempTouchState.windows) {
2761*38e8c45fSAndroid Build Coastguard Worker const auto err = verifyTargetedInjection(touchedWindow.windowHandle, entry);
2762*38e8c45fSAndroid Build Coastguard Worker if (err) errs += "\n - " + *err;
2763*38e8c45fSAndroid Build Coastguard Worker }
2764*38e8c45fSAndroid Build Coastguard Worker if (!errs.empty()) {
2765*38e8c45fSAndroid Build Coastguard Worker ALOGW("Dropping targeted injection: At least one touched window is not owned by uid "
2766*38e8c45fSAndroid Build Coastguard Worker "%s:%s",
2767*38e8c45fSAndroid Build Coastguard Worker entry.injectionState->targetUid->toString().c_str(), errs.c_str());
2768*38e8c45fSAndroid Build Coastguard Worker return injectionError(InputEventInjectionResult::TARGET_MISMATCH);
2769*38e8c45fSAndroid Build Coastguard Worker }
2770*38e8c45fSAndroid Build Coastguard Worker }
2771*38e8c45fSAndroid Build Coastguard Worker
2772*38e8c45fSAndroid Build Coastguard Worker // Check whether windows listening for outside touches are owned by the same UID. If the owner
2773*38e8c45fSAndroid Build Coastguard Worker // has a different UID, then we will not reveal coordinate information to this window.
2774*38e8c45fSAndroid Build Coastguard Worker if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
2775*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> foregroundWindowHandle =
2776*38e8c45fSAndroid Build Coastguard Worker tempTouchState.getFirstForegroundWindowHandle(entry.deviceId);
2777*38e8c45fSAndroid Build Coastguard Worker if (foregroundWindowHandle) {
2778*38e8c45fSAndroid Build Coastguard Worker const auto foregroundWindowUid = foregroundWindowHandle->getInfo()->ownerUid;
2779*38e8c45fSAndroid Build Coastguard Worker for (InputTarget& target : targets) {
2780*38e8c45fSAndroid Build Coastguard Worker if (target.dispatchMode == InputTarget::DispatchMode::OUTSIDE) {
2781*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> targetWindow =
2782*38e8c45fSAndroid Build Coastguard Worker getWindowHandleLocked(target.connection->getToken());
2783*38e8c45fSAndroid Build Coastguard Worker if (targetWindow->getInfo()->ownerUid != foregroundWindowUid) {
2784*38e8c45fSAndroid Build Coastguard Worker target.flags |= InputTarget::Flags::ZERO_COORDS;
2785*38e8c45fSAndroid Build Coastguard Worker }
2786*38e8c45fSAndroid Build Coastguard Worker }
2787*38e8c45fSAndroid Build Coastguard Worker }
2788*38e8c45fSAndroid Build Coastguard Worker }
2789*38e8c45fSAndroid Build Coastguard Worker }
2790*38e8c45fSAndroid Build Coastguard Worker
2791*38e8c45fSAndroid Build Coastguard Worker // If this is a touchpad navigation gesture, it needs to only be sent to trusted targets, as we
2792*38e8c45fSAndroid Build Coastguard Worker // only want the system UI to handle these gestures.
2793*38e8c45fSAndroid Build Coastguard Worker const bool isTouchpadNavGesture = isFromSource(entry.source, AINPUT_SOURCE_MOUSE) &&
2794*38e8c45fSAndroid Build Coastguard Worker entry.classification == MotionClassification::MULTI_FINGER_SWIPE;
2795*38e8c45fSAndroid Build Coastguard Worker if (isTouchpadNavGesture) {
2796*38e8c45fSAndroid Build Coastguard Worker filterUntrustedTargets(/* byref */ tempTouchState, /* byref */ targets);
2797*38e8c45fSAndroid Build Coastguard Worker }
2798*38e8c45fSAndroid Build Coastguard Worker
2799*38e8c45fSAndroid Build Coastguard Worker // Output targets from the touch state.
2800*38e8c45fSAndroid Build Coastguard Worker for (const TouchedWindow& touchedWindow : tempTouchState.windows) {
2801*38e8c45fSAndroid Build Coastguard Worker std::vector<PointerProperties> touchingPointers =
2802*38e8c45fSAndroid Build Coastguard Worker touchedWindow.getTouchingPointers(entry.deviceId);
2803*38e8c45fSAndroid Build Coastguard Worker if (touchingPointers.empty()) {
2804*38e8c45fSAndroid Build Coastguard Worker continue;
2805*38e8c45fSAndroid Build Coastguard Worker }
2806*38e8c45fSAndroid Build Coastguard Worker addPointerWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.dispatchMode,
2807*38e8c45fSAndroid Build Coastguard Worker touchedWindow.targetFlags, getPointerIds(touchingPointers),
2808*38e8c45fSAndroid Build Coastguard Worker touchedWindow.getDownTimeInTarget(entry.deviceId), targets);
2809*38e8c45fSAndroid Build Coastguard Worker }
2810*38e8c45fSAndroid Build Coastguard Worker
2811*38e8c45fSAndroid Build Coastguard Worker // During targeted injection, only allow owned targets to receive events
2812*38e8c45fSAndroid Build Coastguard Worker std::erase_if(targets, [&](const InputTarget& target) {
2813*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(target.windowHandle == nullptr);
2814*38e8c45fSAndroid Build Coastguard Worker const auto err = verifyTargetedInjection(target.windowHandle, entry);
2815*38e8c45fSAndroid Build Coastguard Worker if (err) {
2816*38e8c45fSAndroid Build Coastguard Worker LOG(WARNING) << "Dropping injected event from " << target.windowHandle->getName()
2817*38e8c45fSAndroid Build Coastguard Worker << ": " << (*err);
2818*38e8c45fSAndroid Build Coastguard Worker return true;
2819*38e8c45fSAndroid Build Coastguard Worker }
2820*38e8c45fSAndroid Build Coastguard Worker return false;
2821*38e8c45fSAndroid Build Coastguard Worker });
2822*38e8c45fSAndroid Build Coastguard Worker
2823*38e8c45fSAndroid Build Coastguard Worker if (targets.empty()) {
2824*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "Dropping event because no targets were found: " << entry.getDescription();
2825*38e8c45fSAndroid Build Coastguard Worker return injectionError(InputEventInjectionResult::FAILED);
2826*38e8c45fSAndroid Build Coastguard Worker }
2827*38e8c45fSAndroid Build Coastguard Worker
2828*38e8c45fSAndroid Build Coastguard Worker // If we only have windows getting ACTION_OUTSIDE, then drop the event, because there is no
2829*38e8c45fSAndroid Build Coastguard Worker // window that is actually receiving the entire gesture.
2830*38e8c45fSAndroid Build Coastguard Worker if (std::all_of(targets.begin(), targets.end(), [](const InputTarget& target) {
2831*38e8c45fSAndroid Build Coastguard Worker return target.dispatchMode == InputTarget::DispatchMode::OUTSIDE;
2832*38e8c45fSAndroid Build Coastguard Worker })) {
2833*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "Dropping event because all windows would just receive ACTION_OUTSIDE: "
2834*38e8c45fSAndroid Build Coastguard Worker << entry.getDescription();
2835*38e8c45fSAndroid Build Coastguard Worker return injectionError(InputEventInjectionResult::FAILED);
2836*38e8c45fSAndroid Build Coastguard Worker }
2837*38e8c45fSAndroid Build Coastguard Worker
2838*38e8c45fSAndroid Build Coastguard Worker // Now that we have generated all of the input targets for this event, reset the dispatch
2839*38e8c45fSAndroid Build Coastguard Worker // mode for all touched window to AS_IS.
2840*38e8c45fSAndroid Build Coastguard Worker for (TouchedWindow& touchedWindow : tempTouchState.windows) {
2841*38e8c45fSAndroid Build Coastguard Worker touchedWindow.dispatchMode = InputTarget::DispatchMode::AS_IS;
2842*38e8c45fSAndroid Build Coastguard Worker }
2843*38e8c45fSAndroid Build Coastguard Worker
2844*38e8c45fSAndroid Build Coastguard Worker // Update final pieces of touch state if the injector had permission.
2845*38e8c45fSAndroid Build Coastguard Worker if (maskedAction == AMOTION_EVENT_ACTION_UP) {
2846*38e8c45fSAndroid Build Coastguard Worker // Pointer went up.
2847*38e8c45fSAndroid Build Coastguard Worker tempTouchState.removeTouchingPointer(entry.deviceId, entry.pointerProperties[0].id);
2848*38e8c45fSAndroid Build Coastguard Worker } else if (maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
2849*38e8c45fSAndroid Build Coastguard Worker // All pointers up or canceled.
2850*38e8c45fSAndroid Build Coastguard Worker tempTouchState.removeAllPointersForDevice(entry.deviceId);
2851*38e8c45fSAndroid Build Coastguard Worker } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
2852*38e8c45fSAndroid Build Coastguard Worker // One pointer went up.
2853*38e8c45fSAndroid Build Coastguard Worker const int32_t pointerIndex = MotionEvent::getActionIndex(action);
2854*38e8c45fSAndroid Build Coastguard Worker const uint32_t pointerId = entry.pointerProperties[pointerIndex].id;
2855*38e8c45fSAndroid Build Coastguard Worker tempTouchState.removeTouchingPointer(entry.deviceId, pointerId);
2856*38e8c45fSAndroid Build Coastguard Worker }
2857*38e8c45fSAndroid Build Coastguard Worker
2858*38e8c45fSAndroid Build Coastguard Worker // Save changes unless the action was scroll in which case the temporary touch
2859*38e8c45fSAndroid Build Coastguard Worker // state was only valid for this one action.
2860*38e8c45fSAndroid Build Coastguard Worker if (maskedAction != AMOTION_EVENT_ACTION_SCROLL) {
2861*38e8c45fSAndroid Build Coastguard Worker if (displayId >= ui::LogicalDisplayId::DEFAULT) {
2862*38e8c45fSAndroid Build Coastguard Worker tempTouchState.clearWindowsWithoutPointers();
2863*38e8c45fSAndroid Build Coastguard Worker mTouchStatesByDisplay[displayId] = tempTouchState;
2864*38e8c45fSAndroid Build Coastguard Worker } else {
2865*38e8c45fSAndroid Build Coastguard Worker mTouchStatesByDisplay.erase(displayId);
2866*38e8c45fSAndroid Build Coastguard Worker }
2867*38e8c45fSAndroid Build Coastguard Worker }
2868*38e8c45fSAndroid Build Coastguard Worker
2869*38e8c45fSAndroid Build Coastguard Worker if (tempTouchState.windows.empty()) {
2870*38e8c45fSAndroid Build Coastguard Worker mTouchStatesByDisplay.erase(displayId);
2871*38e8c45fSAndroid Build Coastguard Worker }
2872*38e8c45fSAndroid Build Coastguard Worker
2873*38e8c45fSAndroid Build Coastguard Worker return targets;
2874*38e8c45fSAndroid Build Coastguard Worker }
2875*38e8c45fSAndroid Build Coastguard Worker
finishDragAndDrop(ui::LogicalDisplayId displayId,float x,float y)2876*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::finishDragAndDrop(ui::LogicalDisplayId displayId, float x, float y) {
2877*38e8c45fSAndroid Build Coastguard Worker // Prevent stylus interceptor windows from affecting drag and drop behavior for now, until we
2878*38e8c45fSAndroid Build Coastguard Worker // have an explicit reason to support it.
2879*38e8c45fSAndroid Build Coastguard Worker constexpr bool isStylus = false;
2880*38e8c45fSAndroid Build Coastguard Worker
2881*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> dropWindow =
2882*38e8c45fSAndroid Build Coastguard Worker findTouchedWindowAtLocked(displayId, x, y, isStylus, /*ignoreDragWindow=*/true);
2883*38e8c45fSAndroid Build Coastguard Worker if (dropWindow) {
2884*38e8c45fSAndroid Build Coastguard Worker vec2 local = dropWindow->getInfo()->transform.transform(x, y);
2885*38e8c45fSAndroid Build Coastguard Worker sendDropWindowCommandLocked(dropWindow->getToken(), local.x, local.y);
2886*38e8c45fSAndroid Build Coastguard Worker } else {
2887*38e8c45fSAndroid Build Coastguard Worker ALOGW("No window found when drop.");
2888*38e8c45fSAndroid Build Coastguard Worker sendDropWindowCommandLocked(nullptr, 0, 0);
2889*38e8c45fSAndroid Build Coastguard Worker }
2890*38e8c45fSAndroid Build Coastguard Worker mDragState.reset();
2891*38e8c45fSAndroid Build Coastguard Worker }
2892*38e8c45fSAndroid Build Coastguard Worker
addDragEventLocked(const MotionEntry & entry)2893*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::addDragEventLocked(const MotionEntry& entry) {
2894*38e8c45fSAndroid Build Coastguard Worker if (!mDragState || mDragState->dragWindow->getInfo()->displayId != entry.displayId ||
2895*38e8c45fSAndroid Build Coastguard Worker mDragState->deviceId != entry.deviceId) {
2896*38e8c45fSAndroid Build Coastguard Worker return;
2897*38e8c45fSAndroid Build Coastguard Worker }
2898*38e8c45fSAndroid Build Coastguard Worker
2899*38e8c45fSAndroid Build Coastguard Worker if (!mDragState->isStartDrag) {
2900*38e8c45fSAndroid Build Coastguard Worker mDragState->isStartDrag = true;
2901*38e8c45fSAndroid Build Coastguard Worker mDragState->isStylusButtonDownAtStart =
2902*38e8c45fSAndroid Build Coastguard Worker (entry.buttonState & AMOTION_EVENT_BUTTON_STYLUS_PRIMARY) != 0;
2903*38e8c45fSAndroid Build Coastguard Worker }
2904*38e8c45fSAndroid Build Coastguard Worker
2905*38e8c45fSAndroid Build Coastguard Worker // Find the pointer index by id.
2906*38e8c45fSAndroid Build Coastguard Worker int32_t pointerIndex = 0;
2907*38e8c45fSAndroid Build Coastguard Worker for (; static_cast<uint32_t>(pointerIndex) < entry.getPointerCount(); pointerIndex++) {
2908*38e8c45fSAndroid Build Coastguard Worker const PointerProperties& pointerProperties = entry.pointerProperties[pointerIndex];
2909*38e8c45fSAndroid Build Coastguard Worker if (pointerProperties.id == mDragState->pointerId) {
2910*38e8c45fSAndroid Build Coastguard Worker break;
2911*38e8c45fSAndroid Build Coastguard Worker }
2912*38e8c45fSAndroid Build Coastguard Worker }
2913*38e8c45fSAndroid Build Coastguard Worker
2914*38e8c45fSAndroid Build Coastguard Worker if (uint32_t(pointerIndex) == entry.getPointerCount()) {
2915*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("Should find a valid pointer index by id %d", mDragState->pointerId);
2916*38e8c45fSAndroid Build Coastguard Worker }
2917*38e8c45fSAndroid Build Coastguard Worker
2918*38e8c45fSAndroid Build Coastguard Worker const int32_t maskedAction = entry.action & AMOTION_EVENT_ACTION_MASK;
2919*38e8c45fSAndroid Build Coastguard Worker const int32_t x = entry.pointerCoords[pointerIndex].getX();
2920*38e8c45fSAndroid Build Coastguard Worker const int32_t y = entry.pointerCoords[pointerIndex].getY();
2921*38e8c45fSAndroid Build Coastguard Worker
2922*38e8c45fSAndroid Build Coastguard Worker switch (maskedAction) {
2923*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_MOVE: {
2924*38e8c45fSAndroid Build Coastguard Worker // Handle the special case : stylus button no longer pressed.
2925*38e8c45fSAndroid Build Coastguard Worker bool isStylusButtonDown =
2926*38e8c45fSAndroid Build Coastguard Worker (entry.buttonState & AMOTION_EVENT_BUTTON_STYLUS_PRIMARY) != 0;
2927*38e8c45fSAndroid Build Coastguard Worker if (mDragState->isStylusButtonDownAtStart && !isStylusButtonDown) {
2928*38e8c45fSAndroid Build Coastguard Worker finishDragAndDrop(entry.displayId, x, y);
2929*38e8c45fSAndroid Build Coastguard Worker return;
2930*38e8c45fSAndroid Build Coastguard Worker }
2931*38e8c45fSAndroid Build Coastguard Worker
2932*38e8c45fSAndroid Build Coastguard Worker // Prevent stylus interceptor windows from affecting drag and drop behavior for now,
2933*38e8c45fSAndroid Build Coastguard Worker // until we have an explicit reason to support it.
2934*38e8c45fSAndroid Build Coastguard Worker constexpr bool isStylus = false;
2935*38e8c45fSAndroid Build Coastguard Worker
2936*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> hoverWindowHandle =
2937*38e8c45fSAndroid Build Coastguard Worker findTouchedWindowAtLocked(entry.displayId, x, y, isStylus,
2938*38e8c45fSAndroid Build Coastguard Worker /*ignoreDragWindow=*/true);
2939*38e8c45fSAndroid Build Coastguard Worker // enqueue drag exit if needed.
2940*38e8c45fSAndroid Build Coastguard Worker if (hoverWindowHandle != mDragState->dragHoverWindowHandle &&
2941*38e8c45fSAndroid Build Coastguard Worker !haveSameToken(hoverWindowHandle, mDragState->dragHoverWindowHandle)) {
2942*38e8c45fSAndroid Build Coastguard Worker if (mDragState->dragHoverWindowHandle != nullptr) {
2943*38e8c45fSAndroid Build Coastguard Worker enqueueDragEventLocked(mDragState->dragHoverWindowHandle, /*isExiting=*/true, x,
2944*38e8c45fSAndroid Build Coastguard Worker y);
2945*38e8c45fSAndroid Build Coastguard Worker }
2946*38e8c45fSAndroid Build Coastguard Worker mDragState->dragHoverWindowHandle = hoverWindowHandle;
2947*38e8c45fSAndroid Build Coastguard Worker }
2948*38e8c45fSAndroid Build Coastguard Worker // enqueue drag location if needed.
2949*38e8c45fSAndroid Build Coastguard Worker if (hoverWindowHandle != nullptr) {
2950*38e8c45fSAndroid Build Coastguard Worker enqueueDragEventLocked(hoverWindowHandle, /*isExiting=*/false, x, y);
2951*38e8c45fSAndroid Build Coastguard Worker }
2952*38e8c45fSAndroid Build Coastguard Worker break;
2953*38e8c45fSAndroid Build Coastguard Worker }
2954*38e8c45fSAndroid Build Coastguard Worker
2955*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_POINTER_UP:
2956*38e8c45fSAndroid Build Coastguard Worker if (MotionEvent::getActionIndex(entry.action) != pointerIndex) {
2957*38e8c45fSAndroid Build Coastguard Worker break;
2958*38e8c45fSAndroid Build Coastguard Worker }
2959*38e8c45fSAndroid Build Coastguard Worker // The drag pointer is up.
2960*38e8c45fSAndroid Build Coastguard Worker [[fallthrough]];
2961*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_UP:
2962*38e8c45fSAndroid Build Coastguard Worker finishDragAndDrop(entry.displayId, x, y);
2963*38e8c45fSAndroid Build Coastguard Worker break;
2964*38e8c45fSAndroid Build Coastguard Worker case AMOTION_EVENT_ACTION_CANCEL: {
2965*38e8c45fSAndroid Build Coastguard Worker ALOGD("Receiving cancel when drag and drop.");
2966*38e8c45fSAndroid Build Coastguard Worker sendDropWindowCommandLocked(nullptr, 0, 0);
2967*38e8c45fSAndroid Build Coastguard Worker mDragState.reset();
2968*38e8c45fSAndroid Build Coastguard Worker break;
2969*38e8c45fSAndroid Build Coastguard Worker }
2970*38e8c45fSAndroid Build Coastguard Worker }
2971*38e8c45fSAndroid Build Coastguard Worker }
2972*38e8c45fSAndroid Build Coastguard Worker
createInputTargetLocked(const sp<android::gui::WindowInfoHandle> & windowHandle,InputTarget::DispatchMode dispatchMode,ftl::Flags<InputTarget::Flags> targetFlags,std::optional<nsecs_t> firstDownTimeInTarget) const2973*38e8c45fSAndroid Build Coastguard Worker std::optional<InputTarget> InputDispatcher::createInputTargetLocked(
2974*38e8c45fSAndroid Build Coastguard Worker const sp<android::gui::WindowInfoHandle>& windowHandle,
2975*38e8c45fSAndroid Build Coastguard Worker InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags,
2976*38e8c45fSAndroid Build Coastguard Worker std::optional<nsecs_t> firstDownTimeInTarget) const {
2977*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<Connection> connection = getConnectionLocked(windowHandle->getToken());
2978*38e8c45fSAndroid Build Coastguard Worker if (connection == nullptr) {
2979*38e8c45fSAndroid Build Coastguard Worker ALOGW("Not creating InputTarget for %s, no input channel", windowHandle->getName().c_str());
2980*38e8c45fSAndroid Build Coastguard Worker return {};
2981*38e8c45fSAndroid Build Coastguard Worker }
2982*38e8c45fSAndroid Build Coastguard Worker InputTarget inputTarget{connection};
2983*38e8c45fSAndroid Build Coastguard Worker inputTarget.windowHandle = windowHandle;
2984*38e8c45fSAndroid Build Coastguard Worker inputTarget.dispatchMode = dispatchMode;
2985*38e8c45fSAndroid Build Coastguard Worker inputTarget.flags = targetFlags;
2986*38e8c45fSAndroid Build Coastguard Worker inputTarget.globalScaleFactor = windowHandle->getInfo()->globalScaleFactor;
2987*38e8c45fSAndroid Build Coastguard Worker inputTarget.firstDownTimeInTarget = firstDownTimeInTarget;
2988*38e8c45fSAndroid Build Coastguard Worker const auto& displayInfoIt = mDisplayInfos.find(windowHandle->getInfo()->displayId);
2989*38e8c45fSAndroid Build Coastguard Worker if (displayInfoIt != mDisplayInfos.end()) {
2990*38e8c45fSAndroid Build Coastguard Worker inputTarget.displayTransform = displayInfoIt->second.transform;
2991*38e8c45fSAndroid Build Coastguard Worker } else {
2992*38e8c45fSAndroid Build Coastguard Worker // DisplayInfo not found for this window on display windowHandle->getInfo()->displayId.
2993*38e8c45fSAndroid Build Coastguard Worker // TODO(b/198444055): Make this an error message after 'setInputWindows' API is removed.
2994*38e8c45fSAndroid Build Coastguard Worker }
2995*38e8c45fSAndroid Build Coastguard Worker return inputTarget;
2996*38e8c45fSAndroid Build Coastguard Worker }
2997*38e8c45fSAndroid Build Coastguard Worker
addWindowTargetLocked(const sp<WindowInfoHandle> & windowHandle,InputTarget::DispatchMode dispatchMode,ftl::Flags<InputTarget::Flags> targetFlags,std::optional<nsecs_t> firstDownTimeInTarget,std::vector<InputTarget> & inputTargets) const2998*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::addWindowTargetLocked(const sp<WindowInfoHandle>& windowHandle,
2999*38e8c45fSAndroid Build Coastguard Worker InputTarget::DispatchMode dispatchMode,
3000*38e8c45fSAndroid Build Coastguard Worker ftl::Flags<InputTarget::Flags> targetFlags,
3001*38e8c45fSAndroid Build Coastguard Worker std::optional<nsecs_t> firstDownTimeInTarget,
3002*38e8c45fSAndroid Build Coastguard Worker std::vector<InputTarget>& inputTargets) const {
3003*38e8c45fSAndroid Build Coastguard Worker std::vector<InputTarget>::iterator it =
3004*38e8c45fSAndroid Build Coastguard Worker std::find_if(inputTargets.begin(), inputTargets.end(),
3005*38e8c45fSAndroid Build Coastguard Worker [&windowHandle](const InputTarget& inputTarget) {
3006*38e8c45fSAndroid Build Coastguard Worker return inputTarget.connection->getToken() == windowHandle->getToken();
3007*38e8c45fSAndroid Build Coastguard Worker });
3008*38e8c45fSAndroid Build Coastguard Worker
3009*38e8c45fSAndroid Build Coastguard Worker const WindowInfo* windowInfo = windowHandle->getInfo();
3010*38e8c45fSAndroid Build Coastguard Worker
3011*38e8c45fSAndroid Build Coastguard Worker if (it == inputTargets.end()) {
3012*38e8c45fSAndroid Build Coastguard Worker std::optional<InputTarget> target =
3013*38e8c45fSAndroid Build Coastguard Worker createInputTargetLocked(windowHandle, dispatchMode, targetFlags,
3014*38e8c45fSAndroid Build Coastguard Worker firstDownTimeInTarget);
3015*38e8c45fSAndroid Build Coastguard Worker if (!target) {
3016*38e8c45fSAndroid Build Coastguard Worker return;
3017*38e8c45fSAndroid Build Coastguard Worker }
3018*38e8c45fSAndroid Build Coastguard Worker inputTargets.push_back(*target);
3019*38e8c45fSAndroid Build Coastguard Worker it = inputTargets.end() - 1;
3020*38e8c45fSAndroid Build Coastguard Worker }
3021*38e8c45fSAndroid Build Coastguard Worker
3022*38e8c45fSAndroid Build Coastguard Worker if (it->flags != targetFlags) {
3023*38e8c45fSAndroid Build Coastguard Worker LOG(ERROR) << "Flags don't match! targetFlags=" << targetFlags.string() << ", it=" << *it;
3024*38e8c45fSAndroid Build Coastguard Worker }
3025*38e8c45fSAndroid Build Coastguard Worker if (it->globalScaleFactor != windowInfo->globalScaleFactor) {
3026*38e8c45fSAndroid Build Coastguard Worker LOG(ERROR) << "Mismatch! it->globalScaleFactor=" << it->globalScaleFactor
3027*38e8c45fSAndroid Build Coastguard Worker << ", windowInfo->globalScaleFactor=" << windowInfo->globalScaleFactor;
3028*38e8c45fSAndroid Build Coastguard Worker }
3029*38e8c45fSAndroid Build Coastguard Worker }
3030*38e8c45fSAndroid Build Coastguard Worker
addPointerWindowTargetLocked(const sp<android::gui::WindowInfoHandle> & windowHandle,InputTarget::DispatchMode dispatchMode,ftl::Flags<InputTarget::Flags> targetFlags,std::bitset<MAX_POINTER_ID+1> pointerIds,std::optional<nsecs_t> firstDownTimeInTarget,std::vector<InputTarget> & inputTargets) const3031*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::addPointerWindowTargetLocked(
3032*38e8c45fSAndroid Build Coastguard Worker const sp<android::gui::WindowInfoHandle>& windowHandle,
3033*38e8c45fSAndroid Build Coastguard Worker InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags,
3034*38e8c45fSAndroid Build Coastguard Worker std::bitset<MAX_POINTER_ID + 1> pointerIds, std::optional<nsecs_t> firstDownTimeInTarget,
3035*38e8c45fSAndroid Build Coastguard Worker std::vector<InputTarget>& inputTargets) const REQUIRES(mLock) {
3036*38e8c45fSAndroid Build Coastguard Worker if (pointerIds.none()) {
3037*38e8c45fSAndroid Build Coastguard Worker for (const auto& target : inputTargets) {
3038*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "Target: " << target;
3039*38e8c45fSAndroid Build Coastguard Worker }
3040*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << "No pointers specified for " << windowHandle->getName();
3041*38e8c45fSAndroid Build Coastguard Worker return;
3042*38e8c45fSAndroid Build Coastguard Worker }
3043*38e8c45fSAndroid Build Coastguard Worker std::vector<InputTarget>::iterator it =
3044*38e8c45fSAndroid Build Coastguard Worker std::find_if(inputTargets.begin(), inputTargets.end(),
3045*38e8c45fSAndroid Build Coastguard Worker [&windowHandle](const InputTarget& inputTarget) {
3046*38e8c45fSAndroid Build Coastguard Worker return inputTarget.connection->getToken() == windowHandle->getToken();
3047*38e8c45fSAndroid Build Coastguard Worker });
3048*38e8c45fSAndroid Build Coastguard Worker
3049*38e8c45fSAndroid Build Coastguard Worker // This is a hack, because the actual entry could potentially be an ACTION_DOWN event that
3050*38e8c45fSAndroid Build Coastguard Worker // causes a HOVER_EXIT to be generated. That means that the same entry of ACTION_DOWN would
3051*38e8c45fSAndroid Build Coastguard Worker // have DISPATCH_AS_HOVER_EXIT and DISPATCH_AS_IS. And therefore, we have to create separate
3052*38e8c45fSAndroid Build Coastguard Worker // input targets for hovering pointers and for touching pointers.
3053*38e8c45fSAndroid Build Coastguard Worker // If we picked an existing input target above, but it's for HOVER_EXIT - let's use a new
3054*38e8c45fSAndroid Build Coastguard Worker // target instead.
3055*38e8c45fSAndroid Build Coastguard Worker if (it != inputTargets.end() && it->dispatchMode == InputTarget::DispatchMode::HOVER_EXIT) {
3056*38e8c45fSAndroid Build Coastguard Worker // Force the code below to create a new input target
3057*38e8c45fSAndroid Build Coastguard Worker it = inputTargets.end();
3058*38e8c45fSAndroid Build Coastguard Worker }
3059*38e8c45fSAndroid Build Coastguard Worker
3060*38e8c45fSAndroid Build Coastguard Worker const WindowInfo* windowInfo = windowHandle->getInfo();
3061*38e8c45fSAndroid Build Coastguard Worker
3062*38e8c45fSAndroid Build Coastguard Worker if (it == inputTargets.end()) {
3063*38e8c45fSAndroid Build Coastguard Worker std::optional<InputTarget> target =
3064*38e8c45fSAndroid Build Coastguard Worker createInputTargetLocked(windowHandle, dispatchMode, targetFlags,
3065*38e8c45fSAndroid Build Coastguard Worker firstDownTimeInTarget);
3066*38e8c45fSAndroid Build Coastguard Worker if (!target) {
3067*38e8c45fSAndroid Build Coastguard Worker return;
3068*38e8c45fSAndroid Build Coastguard Worker }
3069*38e8c45fSAndroid Build Coastguard Worker inputTargets.push_back(*target);
3070*38e8c45fSAndroid Build Coastguard Worker it = inputTargets.end() - 1;
3071*38e8c45fSAndroid Build Coastguard Worker }
3072*38e8c45fSAndroid Build Coastguard Worker
3073*38e8c45fSAndroid Build Coastguard Worker if (it->dispatchMode != dispatchMode) {
3074*38e8c45fSAndroid Build Coastguard Worker LOG(ERROR) << __func__ << ": DispatchMode doesn't match! ignoring new mode="
3075*38e8c45fSAndroid Build Coastguard Worker << ftl::enum_string(dispatchMode) << ", it=" << *it;
3076*38e8c45fSAndroid Build Coastguard Worker }
3077*38e8c45fSAndroid Build Coastguard Worker if (it->flags != targetFlags) {
3078*38e8c45fSAndroid Build Coastguard Worker LOG(ERROR) << __func__ << ": Flags don't match! new targetFlags=" << targetFlags.string()
3079*38e8c45fSAndroid Build Coastguard Worker << ", it=" << *it;
3080*38e8c45fSAndroid Build Coastguard Worker }
3081*38e8c45fSAndroid Build Coastguard Worker if (it->globalScaleFactor != windowInfo->globalScaleFactor) {
3082*38e8c45fSAndroid Build Coastguard Worker LOG(ERROR) << __func__ << ": Mismatch! it->globalScaleFactor=" << it->globalScaleFactor
3083*38e8c45fSAndroid Build Coastguard Worker << ", windowInfo->globalScaleFactor=" << windowInfo->globalScaleFactor;
3084*38e8c45fSAndroid Build Coastguard Worker }
3085*38e8c45fSAndroid Build Coastguard Worker
3086*38e8c45fSAndroid Build Coastguard Worker Result<void> result = it->addPointers(pointerIds, windowInfo->transform);
3087*38e8c45fSAndroid Build Coastguard Worker if (!result.ok()) {
3088*38e8c45fSAndroid Build Coastguard Worker logDispatchStateLocked();
3089*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << result.error().message();
3090*38e8c45fSAndroid Build Coastguard Worker }
3091*38e8c45fSAndroid Build Coastguard Worker }
3092*38e8c45fSAndroid Build Coastguard Worker
addGlobalMonitoringTargetsLocked(std::vector<InputTarget> & inputTargets,ui::LogicalDisplayId displayId)3093*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets,
3094*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId displayId) {
3095*38e8c45fSAndroid Build Coastguard Worker auto monitorsIt = mGlobalMonitorsByDisplay.find(displayId);
3096*38e8c45fSAndroid Build Coastguard Worker if (monitorsIt == mGlobalMonitorsByDisplay.end()) return;
3097*38e8c45fSAndroid Build Coastguard Worker
3098*38e8c45fSAndroid Build Coastguard Worker for (const Monitor& monitor : selectResponsiveMonitorsLocked(monitorsIt->second)) {
3099*38e8c45fSAndroid Build Coastguard Worker InputTarget target{monitor.connection};
3100*38e8c45fSAndroid Build Coastguard Worker // target.firstDownTimeInTarget is not set for global monitors. It is only required in split
3101*38e8c45fSAndroid Build Coastguard Worker // touch and global monitoring works as intended even without setting firstDownTimeInTarget
3102*38e8c45fSAndroid Build Coastguard Worker if (const auto& it = mDisplayInfos.find(displayId); it != mDisplayInfos.end()) {
3103*38e8c45fSAndroid Build Coastguard Worker target.displayTransform = it->second.transform;
3104*38e8c45fSAndroid Build Coastguard Worker }
3105*38e8c45fSAndroid Build Coastguard Worker target.setDefaultPointerTransform(target.displayTransform);
3106*38e8c45fSAndroid Build Coastguard Worker inputTargets.push_back(target);
3107*38e8c45fSAndroid Build Coastguard Worker }
3108*38e8c45fSAndroid Build Coastguard Worker }
3109*38e8c45fSAndroid Build Coastguard Worker
3110*38e8c45fSAndroid Build Coastguard Worker /**
3111*38e8c45fSAndroid Build Coastguard Worker * Indicate whether one window handle should be considered as obscuring
3112*38e8c45fSAndroid Build Coastguard Worker * another window handle. We only check a few preconditions. Actually
3113*38e8c45fSAndroid Build Coastguard Worker * checking the bounds is left to the caller.
3114*38e8c45fSAndroid Build Coastguard Worker */
canBeObscuredBy(const sp<WindowInfoHandle> & windowHandle,const sp<WindowInfoHandle> & otherHandle)3115*38e8c45fSAndroid Build Coastguard Worker static bool canBeObscuredBy(const sp<WindowInfoHandle>& windowHandle,
3116*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle>& otherHandle) {
3117*38e8c45fSAndroid Build Coastguard Worker // Compare by token so cloned layers aren't counted
3118*38e8c45fSAndroid Build Coastguard Worker if (haveSameToken(windowHandle, otherHandle)) {
3119*38e8c45fSAndroid Build Coastguard Worker return false;
3120*38e8c45fSAndroid Build Coastguard Worker }
3121*38e8c45fSAndroid Build Coastguard Worker auto info = windowHandle->getInfo();
3122*38e8c45fSAndroid Build Coastguard Worker auto otherInfo = otherHandle->getInfo();
3123*38e8c45fSAndroid Build Coastguard Worker if (otherInfo->inputConfig.test(WindowInfo::InputConfig::NOT_VISIBLE)) {
3124*38e8c45fSAndroid Build Coastguard Worker return false;
3125*38e8c45fSAndroid Build Coastguard Worker } else if (otherInfo->alpha == 0 &&
3126*38e8c45fSAndroid Build Coastguard Worker otherInfo->inputConfig.test(WindowInfo::InputConfig::NOT_TOUCHABLE)) {
3127*38e8c45fSAndroid Build Coastguard Worker // Those act as if they were invisible, so we don't need to flag them.
3128*38e8c45fSAndroid Build Coastguard Worker // We do want to potentially flag touchable windows even if they have 0
3129*38e8c45fSAndroid Build Coastguard Worker // opacity, since they can consume touches and alter the effects of the
3130*38e8c45fSAndroid Build Coastguard Worker // user interaction (eg. apps that rely on
3131*38e8c45fSAndroid Build Coastguard Worker // Flags::WINDOW_IS_PARTIALLY_OBSCURED should still be told about those
3132*38e8c45fSAndroid Build Coastguard Worker // windows), hence we also check for FLAG_NOT_TOUCHABLE.
3133*38e8c45fSAndroid Build Coastguard Worker return false;
3134*38e8c45fSAndroid Build Coastguard Worker } else if (info->ownerUid == otherInfo->ownerUid) {
3135*38e8c45fSAndroid Build Coastguard Worker // If ownerUid is the same we don't generate occlusion events as there
3136*38e8c45fSAndroid Build Coastguard Worker // is no security boundary within an uid.
3137*38e8c45fSAndroid Build Coastguard Worker return false;
3138*38e8c45fSAndroid Build Coastguard Worker } else if (otherInfo->inputConfig.test(gui::WindowInfo::InputConfig::TRUSTED_OVERLAY)) {
3139*38e8c45fSAndroid Build Coastguard Worker return false;
3140*38e8c45fSAndroid Build Coastguard Worker } else if (otherInfo->displayId != info->displayId) {
3141*38e8c45fSAndroid Build Coastguard Worker return false;
3142*38e8c45fSAndroid Build Coastguard Worker }
3143*38e8c45fSAndroid Build Coastguard Worker return true;
3144*38e8c45fSAndroid Build Coastguard Worker }
3145*38e8c45fSAndroid Build Coastguard Worker
3146*38e8c45fSAndroid Build Coastguard Worker /**
3147*38e8c45fSAndroid Build Coastguard Worker * Returns touch occlusion information in the form of TouchOcclusionInfo. To check if the touch is
3148*38e8c45fSAndroid Build Coastguard Worker * untrusted, one should check:
3149*38e8c45fSAndroid Build Coastguard Worker *
3150*38e8c45fSAndroid Build Coastguard Worker * 1. If result.hasBlockingOcclusion is true.
3151*38e8c45fSAndroid Build Coastguard Worker * If it's, it means the touch should be blocked due to a window with occlusion mode of
3152*38e8c45fSAndroid Build Coastguard Worker * BLOCK_UNTRUSTED.
3153*38e8c45fSAndroid Build Coastguard Worker *
3154*38e8c45fSAndroid Build Coastguard Worker * 2. If result.obscuringOpacity > mMaximumObscuringOpacityForTouch.
3155*38e8c45fSAndroid Build Coastguard Worker * If it is (and 1 is false), then the touch should be blocked because a stack of windows
3156*38e8c45fSAndroid Build Coastguard Worker * (possibly only one) with occlusion mode of USE_OPACITY from one UID resulted in a composed
3157*38e8c45fSAndroid Build Coastguard Worker * obscuring opacity above the threshold. Note that if there was no window of occlusion mode
3158*38e8c45fSAndroid Build Coastguard Worker * USE_OPACITY, result.obscuringOpacity would've been 0 and since
3159*38e8c45fSAndroid Build Coastguard Worker * mMaximumObscuringOpacityForTouch >= 0, the condition above would never be true.
3160*38e8c45fSAndroid Build Coastguard Worker *
3161*38e8c45fSAndroid Build Coastguard Worker * If neither of those is true, then it means the touch can be allowed.
3162*38e8c45fSAndroid Build Coastguard Worker */
computeTouchOcclusionInfoLocked(const sp<WindowInfoHandle> & windowHandle,float x,float y) const3163*38e8c45fSAndroid Build Coastguard Worker InputDispatcher::TouchOcclusionInfo InputDispatcher::computeTouchOcclusionInfoLocked(
3164*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle>& windowHandle, float x, float y) const {
3165*38e8c45fSAndroid Build Coastguard Worker const WindowInfo* windowInfo = windowHandle->getInfo();
3166*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId displayId = windowInfo->displayId;
3167*38e8c45fSAndroid Build Coastguard Worker const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);
3168*38e8c45fSAndroid Build Coastguard Worker TouchOcclusionInfo info;
3169*38e8c45fSAndroid Build Coastguard Worker info.hasBlockingOcclusion = false;
3170*38e8c45fSAndroid Build Coastguard Worker info.obscuringOpacity = 0;
3171*38e8c45fSAndroid Build Coastguard Worker info.obscuringUid = gui::Uid::INVALID;
3172*38e8c45fSAndroid Build Coastguard Worker std::map<gui::Uid, float> opacityByUid;
3173*38e8c45fSAndroid Build Coastguard Worker for (const sp<WindowInfoHandle>& otherHandle : windowHandles) {
3174*38e8c45fSAndroid Build Coastguard Worker if (windowHandle == otherHandle) {
3175*38e8c45fSAndroid Build Coastguard Worker break; // All future windows are below us. Exit early.
3176*38e8c45fSAndroid Build Coastguard Worker }
3177*38e8c45fSAndroid Build Coastguard Worker const WindowInfo* otherInfo = otherHandle->getInfo();
3178*38e8c45fSAndroid Build Coastguard Worker if (canBeObscuredBy(windowHandle, otherHandle) &&
3179*38e8c45fSAndroid Build Coastguard Worker windowOccludesTouchAt(*otherInfo, displayId, x, y, getTransformLocked(displayId)) &&
3180*38e8c45fSAndroid Build Coastguard Worker !haveSameApplicationToken(windowInfo, otherInfo)) {
3181*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_TOUCH_OCCLUSION) {
3182*38e8c45fSAndroid Build Coastguard Worker info.debugInfo.push_back(
3183*38e8c45fSAndroid Build Coastguard Worker dumpWindowForTouchOcclusion(otherInfo, /*isTouchedWindow=*/false));
3184*38e8c45fSAndroid Build Coastguard Worker }
3185*38e8c45fSAndroid Build Coastguard Worker // canBeObscuredBy() has returned true above, which means this window is untrusted, so
3186*38e8c45fSAndroid Build Coastguard Worker // we perform the checks below to see if the touch can be propagated or not based on the
3187*38e8c45fSAndroid Build Coastguard Worker // window's touch occlusion mode
3188*38e8c45fSAndroid Build Coastguard Worker if (otherInfo->touchOcclusionMode == TouchOcclusionMode::BLOCK_UNTRUSTED) {
3189*38e8c45fSAndroid Build Coastguard Worker info.hasBlockingOcclusion = true;
3190*38e8c45fSAndroid Build Coastguard Worker info.obscuringUid = otherInfo->ownerUid;
3191*38e8c45fSAndroid Build Coastguard Worker info.obscuringPackage = otherInfo->packageName;
3192*38e8c45fSAndroid Build Coastguard Worker break;
3193*38e8c45fSAndroid Build Coastguard Worker }
3194*38e8c45fSAndroid Build Coastguard Worker if (otherInfo->touchOcclusionMode == TouchOcclusionMode::USE_OPACITY) {
3195*38e8c45fSAndroid Build Coastguard Worker const auto uid = otherInfo->ownerUid;
3196*38e8c45fSAndroid Build Coastguard Worker float opacity =
3197*38e8c45fSAndroid Build Coastguard Worker (opacityByUid.find(uid) == opacityByUid.end()) ? 0 : opacityByUid[uid];
3198*38e8c45fSAndroid Build Coastguard Worker // Given windows A and B:
3199*38e8c45fSAndroid Build Coastguard Worker // opacity(A, B) = 1 - [1 - opacity(A)] * [1 - opacity(B)]
3200*38e8c45fSAndroid Build Coastguard Worker opacity = 1 - (1 - opacity) * (1 - otherInfo->alpha);
3201*38e8c45fSAndroid Build Coastguard Worker opacityByUid[uid] = opacity;
3202*38e8c45fSAndroid Build Coastguard Worker if (opacity > info.obscuringOpacity) {
3203*38e8c45fSAndroid Build Coastguard Worker info.obscuringOpacity = opacity;
3204*38e8c45fSAndroid Build Coastguard Worker info.obscuringUid = uid;
3205*38e8c45fSAndroid Build Coastguard Worker info.obscuringPackage = otherInfo->packageName;
3206*38e8c45fSAndroid Build Coastguard Worker }
3207*38e8c45fSAndroid Build Coastguard Worker }
3208*38e8c45fSAndroid Build Coastguard Worker }
3209*38e8c45fSAndroid Build Coastguard Worker }
3210*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_TOUCH_OCCLUSION) {
3211*38e8c45fSAndroid Build Coastguard Worker info.debugInfo.push_back(dumpWindowForTouchOcclusion(windowInfo, /*isTouchedWindow=*/true));
3212*38e8c45fSAndroid Build Coastguard Worker }
3213*38e8c45fSAndroid Build Coastguard Worker return info;
3214*38e8c45fSAndroid Build Coastguard Worker }
3215*38e8c45fSAndroid Build Coastguard Worker
dumpWindowForTouchOcclusion(const WindowInfo * info,bool isTouchedWindow) const3216*38e8c45fSAndroid Build Coastguard Worker std::string InputDispatcher::dumpWindowForTouchOcclusion(const WindowInfo* info,
3217*38e8c45fSAndroid Build Coastguard Worker bool isTouchedWindow) const {
3218*38e8c45fSAndroid Build Coastguard Worker return StringPrintf(INDENT2 "* %spackage=%s/%s, id=%" PRId32 ", mode=%s, alpha=%.2f, "
3219*38e8c45fSAndroid Build Coastguard Worker "frame=[%" PRId32 ",%" PRId32 "][%" PRId32 ",%" PRId32
3220*38e8c45fSAndroid Build Coastguard Worker "], touchableRegion=%s, window={%s}, inputConfig={%s}, "
3221*38e8c45fSAndroid Build Coastguard Worker "hasToken=%s, applicationInfo.name=%s, applicationInfo.token=%s\n",
3222*38e8c45fSAndroid Build Coastguard Worker isTouchedWindow ? "[TOUCHED] " : "", info->packageName.c_str(),
3223*38e8c45fSAndroid Build Coastguard Worker info->ownerUid.toString().c_str(), info->id,
3224*38e8c45fSAndroid Build Coastguard Worker toString(info->touchOcclusionMode).c_str(), info->alpha, info->frame.left,
3225*38e8c45fSAndroid Build Coastguard Worker info->frame.top, info->frame.right, info->frame.bottom,
3226*38e8c45fSAndroid Build Coastguard Worker dumpRegion(info->touchableRegion).c_str(), info->name.c_str(),
3227*38e8c45fSAndroid Build Coastguard Worker info->inputConfig.string().c_str(), toString(info->token != nullptr),
3228*38e8c45fSAndroid Build Coastguard Worker info->applicationInfo.name.c_str(),
3229*38e8c45fSAndroid Build Coastguard Worker binderToString(info->applicationInfo.token).c_str());
3230*38e8c45fSAndroid Build Coastguard Worker }
3231*38e8c45fSAndroid Build Coastguard Worker
isTouchTrustedLocked(const TouchOcclusionInfo & occlusionInfo) const3232*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::isTouchTrustedLocked(const TouchOcclusionInfo& occlusionInfo) const {
3233*38e8c45fSAndroid Build Coastguard Worker if (occlusionInfo.hasBlockingOcclusion) {
3234*38e8c45fSAndroid Build Coastguard Worker ALOGW("Untrusted touch due to occlusion by %s/%s", occlusionInfo.obscuringPackage.c_str(),
3235*38e8c45fSAndroid Build Coastguard Worker occlusionInfo.obscuringUid.toString().c_str());
3236*38e8c45fSAndroid Build Coastguard Worker return false;
3237*38e8c45fSAndroid Build Coastguard Worker }
3238*38e8c45fSAndroid Build Coastguard Worker if (occlusionInfo.obscuringOpacity > mMaximumObscuringOpacityForTouch) {
3239*38e8c45fSAndroid Build Coastguard Worker ALOGW("Untrusted touch due to occlusion by %s/%s (obscuring opacity = "
3240*38e8c45fSAndroid Build Coastguard Worker "%.2f, maximum allowed = %.2f)",
3241*38e8c45fSAndroid Build Coastguard Worker occlusionInfo.obscuringPackage.c_str(), occlusionInfo.obscuringUid.toString().c_str(),
3242*38e8c45fSAndroid Build Coastguard Worker occlusionInfo.obscuringOpacity, mMaximumObscuringOpacityForTouch);
3243*38e8c45fSAndroid Build Coastguard Worker return false;
3244*38e8c45fSAndroid Build Coastguard Worker }
3245*38e8c45fSAndroid Build Coastguard Worker return true;
3246*38e8c45fSAndroid Build Coastguard Worker }
3247*38e8c45fSAndroid Build Coastguard Worker
isWindowObscuredAtPointLocked(const sp<WindowInfoHandle> & windowHandle,float x,float y) const3248*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::isWindowObscuredAtPointLocked(const sp<WindowInfoHandle>& windowHandle,
3249*38e8c45fSAndroid Build Coastguard Worker float x, float y) const {
3250*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId displayId = windowHandle->getInfo()->displayId;
3251*38e8c45fSAndroid Build Coastguard Worker const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);
3252*38e8c45fSAndroid Build Coastguard Worker for (const sp<WindowInfoHandle>& otherHandle : windowHandles) {
3253*38e8c45fSAndroid Build Coastguard Worker if (windowHandle == otherHandle) {
3254*38e8c45fSAndroid Build Coastguard Worker break; // All future windows are below us. Exit early.
3255*38e8c45fSAndroid Build Coastguard Worker }
3256*38e8c45fSAndroid Build Coastguard Worker const WindowInfo* otherInfo = otherHandle->getInfo();
3257*38e8c45fSAndroid Build Coastguard Worker if (canBeObscuredBy(windowHandle, otherHandle) &&
3258*38e8c45fSAndroid Build Coastguard Worker windowOccludesTouchAt(*otherInfo, displayId, x, y, getTransformLocked(displayId))) {
3259*38e8c45fSAndroid Build Coastguard Worker return true;
3260*38e8c45fSAndroid Build Coastguard Worker }
3261*38e8c45fSAndroid Build Coastguard Worker }
3262*38e8c45fSAndroid Build Coastguard Worker return false;
3263*38e8c45fSAndroid Build Coastguard Worker }
3264*38e8c45fSAndroid Build Coastguard Worker
isWindowObscuredLocked(const sp<WindowInfoHandle> & windowHandle) const3265*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::isWindowObscuredLocked(const sp<WindowInfoHandle>& windowHandle) const {
3266*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId displayId = windowHandle->getInfo()->displayId;
3267*38e8c45fSAndroid Build Coastguard Worker const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);
3268*38e8c45fSAndroid Build Coastguard Worker const WindowInfo* windowInfo = windowHandle->getInfo();
3269*38e8c45fSAndroid Build Coastguard Worker for (const sp<WindowInfoHandle>& otherHandle : windowHandles) {
3270*38e8c45fSAndroid Build Coastguard Worker if (windowHandle == otherHandle) {
3271*38e8c45fSAndroid Build Coastguard Worker break; // All future windows are below us. Exit early.
3272*38e8c45fSAndroid Build Coastguard Worker }
3273*38e8c45fSAndroid Build Coastguard Worker const WindowInfo* otherInfo = otherHandle->getInfo();
3274*38e8c45fSAndroid Build Coastguard Worker if (canBeObscuredBy(windowHandle, otherHandle) && otherInfo->overlaps(windowInfo)) {
3275*38e8c45fSAndroid Build Coastguard Worker return true;
3276*38e8c45fSAndroid Build Coastguard Worker }
3277*38e8c45fSAndroid Build Coastguard Worker }
3278*38e8c45fSAndroid Build Coastguard Worker return false;
3279*38e8c45fSAndroid Build Coastguard Worker }
3280*38e8c45fSAndroid Build Coastguard Worker
getApplicationWindowLabel(const InputApplicationHandle * applicationHandle,const sp<WindowInfoHandle> & windowHandle)3281*38e8c45fSAndroid Build Coastguard Worker std::string InputDispatcher::getApplicationWindowLabel(
3282*38e8c45fSAndroid Build Coastguard Worker const InputApplicationHandle* applicationHandle, const sp<WindowInfoHandle>& windowHandle) {
3283*38e8c45fSAndroid Build Coastguard Worker if (applicationHandle != nullptr) {
3284*38e8c45fSAndroid Build Coastguard Worker if (windowHandle != nullptr) {
3285*38e8c45fSAndroid Build Coastguard Worker return applicationHandle->getName() + " - " + windowHandle->getName();
3286*38e8c45fSAndroid Build Coastguard Worker } else {
3287*38e8c45fSAndroid Build Coastguard Worker return applicationHandle->getName();
3288*38e8c45fSAndroid Build Coastguard Worker }
3289*38e8c45fSAndroid Build Coastguard Worker } else if (windowHandle != nullptr) {
3290*38e8c45fSAndroid Build Coastguard Worker return windowHandle->getInfo()->applicationInfo.name + " - " + windowHandle->getName();
3291*38e8c45fSAndroid Build Coastguard Worker } else {
3292*38e8c45fSAndroid Build Coastguard Worker return "<unknown application or window>";
3293*38e8c45fSAndroid Build Coastguard Worker }
3294*38e8c45fSAndroid Build Coastguard Worker }
3295*38e8c45fSAndroid Build Coastguard Worker
pokeUserActivityLocked(const EventEntry & eventEntry)3296*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) {
3297*38e8c45fSAndroid Build Coastguard Worker if (!isUserActivityEvent(eventEntry)) {
3298*38e8c45fSAndroid Build Coastguard Worker // Not poking user activity if the event type does not represent a user activity
3299*38e8c45fSAndroid Build Coastguard Worker return;
3300*38e8c45fSAndroid Build Coastguard Worker }
3301*38e8c45fSAndroid Build Coastguard Worker
3302*38e8c45fSAndroid Build Coastguard Worker const int32_t eventType = getUserActivityEventType(eventEntry);
3303*38e8c45fSAndroid Build Coastguard Worker if (input_flags::rate_limit_user_activity_poke_in_dispatcher()) {
3304*38e8c45fSAndroid Build Coastguard Worker // Note that we're directly getting the time diff between the current event and the previous
3305*38e8c45fSAndroid Build Coastguard Worker // event. This is assuming that the first user event always happens at a timestamp that is
3306*38e8c45fSAndroid Build Coastguard Worker // greater than `mMinTimeBetweenUserActivityPokes` (otherwise, the first user event will
3307*38e8c45fSAndroid Build Coastguard Worker // wrongly be dropped). In real life, `mMinTimeBetweenUserActivityPokes` is a much smaller
3308*38e8c45fSAndroid Build Coastguard Worker // value than the potential first user activity event time, so this is ok.
3309*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds timeSinceLastEvent =
3310*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds(eventEntry.eventTime - mLastUserActivityTimes[eventType]);
3311*38e8c45fSAndroid Build Coastguard Worker if (timeSinceLastEvent < mMinTimeBetweenUserActivityPokes) {
3312*38e8c45fSAndroid Build Coastguard Worker return;
3313*38e8c45fSAndroid Build Coastguard Worker }
3314*38e8c45fSAndroid Build Coastguard Worker }
3315*38e8c45fSAndroid Build Coastguard Worker
3316*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId displayId = getTargetDisplayId(eventEntry);
3317*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> focusedWindowHandle = getFocusedWindowHandleLocked(displayId);
3318*38e8c45fSAndroid Build Coastguard Worker const WindowInfo* windowDisablingUserActivityInfo = nullptr;
3319*38e8c45fSAndroid Build Coastguard Worker if (focusedWindowHandle != nullptr) {
3320*38e8c45fSAndroid Build Coastguard Worker const WindowInfo* info = focusedWindowHandle->getInfo();
3321*38e8c45fSAndroid Build Coastguard Worker if (info->inputConfig.test(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY)) {
3322*38e8c45fSAndroid Build Coastguard Worker windowDisablingUserActivityInfo = info;
3323*38e8c45fSAndroid Build Coastguard Worker }
3324*38e8c45fSAndroid Build Coastguard Worker }
3325*38e8c45fSAndroid Build Coastguard Worker
3326*38e8c45fSAndroid Build Coastguard Worker switch (eventEntry.type) {
3327*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::MOTION: {
3328*38e8c45fSAndroid Build Coastguard Worker const MotionEntry& motionEntry = static_cast<const MotionEntry&>(eventEntry);
3329*38e8c45fSAndroid Build Coastguard Worker if (motionEntry.action == AMOTION_EVENT_ACTION_CANCEL) {
3330*38e8c45fSAndroid Build Coastguard Worker return;
3331*38e8c45fSAndroid Build Coastguard Worker }
3332*38e8c45fSAndroid Build Coastguard Worker if (windowDisablingUserActivityInfo != nullptr) {
3333*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_DISPATCH_CYCLE) {
3334*38e8c45fSAndroid Build Coastguard Worker ALOGD("Not poking user activity: disabled by window '%s'.",
3335*38e8c45fSAndroid Build Coastguard Worker windowDisablingUserActivityInfo->name.c_str());
3336*38e8c45fSAndroid Build Coastguard Worker }
3337*38e8c45fSAndroid Build Coastguard Worker return;
3338*38e8c45fSAndroid Build Coastguard Worker }
3339*38e8c45fSAndroid Build Coastguard Worker break;
3340*38e8c45fSAndroid Build Coastguard Worker }
3341*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::KEY: {
3342*38e8c45fSAndroid Build Coastguard Worker const KeyEntry& keyEntry = static_cast<const KeyEntry&>(eventEntry);
3343*38e8c45fSAndroid Build Coastguard Worker if (keyEntry.flags & AKEY_EVENT_FLAG_CANCELED) {
3344*38e8c45fSAndroid Build Coastguard Worker return;
3345*38e8c45fSAndroid Build Coastguard Worker }
3346*38e8c45fSAndroid Build Coastguard Worker // Don't inhibit events that were intercepted or are not passed to
3347*38e8c45fSAndroid Build Coastguard Worker // the apps, like system shortcuts
3348*38e8c45fSAndroid Build Coastguard Worker if (windowDisablingUserActivityInfo != nullptr &&
3349*38e8c45fSAndroid Build Coastguard Worker keyEntry.interceptKeyResult != KeyEntry::InterceptKeyResult::SKIP) {
3350*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_DISPATCH_CYCLE) {
3351*38e8c45fSAndroid Build Coastguard Worker ALOGD("Not poking user activity: disabled by window '%s'.",
3352*38e8c45fSAndroid Build Coastguard Worker windowDisablingUserActivityInfo->name.c_str());
3353*38e8c45fSAndroid Build Coastguard Worker }
3354*38e8c45fSAndroid Build Coastguard Worker return;
3355*38e8c45fSAndroid Build Coastguard Worker }
3356*38e8c45fSAndroid Build Coastguard Worker break;
3357*38e8c45fSAndroid Build Coastguard Worker }
3358*38e8c45fSAndroid Build Coastguard Worker default: {
3359*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("%s events are not user activity",
3360*38e8c45fSAndroid Build Coastguard Worker ftl::enum_string(eventEntry.type).c_str());
3361*38e8c45fSAndroid Build Coastguard Worker break;
3362*38e8c45fSAndroid Build Coastguard Worker }
3363*38e8c45fSAndroid Build Coastguard Worker }
3364*38e8c45fSAndroid Build Coastguard Worker
3365*38e8c45fSAndroid Build Coastguard Worker mLastUserActivityTimes[eventType] = eventEntry.eventTime;
3366*38e8c45fSAndroid Build Coastguard Worker auto command = [this, eventTime = eventEntry.eventTime, eventType, displayId]()
3367*38e8c45fSAndroid Build Coastguard Worker REQUIRES(mLock) {
3368*38e8c45fSAndroid Build Coastguard Worker scoped_unlock unlock(mLock);
3369*38e8c45fSAndroid Build Coastguard Worker mPolicy.pokeUserActivity(eventTime, eventType, displayId);
3370*38e8c45fSAndroid Build Coastguard Worker };
3371*38e8c45fSAndroid Build Coastguard Worker postCommandLocked(std::move(command));
3372*38e8c45fSAndroid Build Coastguard Worker }
3373*38e8c45fSAndroid Build Coastguard Worker
prepareDispatchCycleLocked(nsecs_t currentTime,const std::shared_ptr<Connection> & connection,std::shared_ptr<const EventEntry> eventEntry,const InputTarget & inputTarget)3374*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
3375*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<Connection>& connection,
3376*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const EventEntry> eventEntry,
3377*38e8c45fSAndroid Build Coastguard Worker const InputTarget& inputTarget) {
3378*38e8c45fSAndroid Build Coastguard Worker ATRACE_NAME_IF(ATRACE_ENABLED(),
3379*38e8c45fSAndroid Build Coastguard Worker StringPrintf("prepareDispatchCycleLocked(inputChannel=%s, id=0x%" PRIx32 ")",
3380*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str(), eventEntry->id));
3381*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_DISPATCH_CYCLE) {
3382*38e8c45fSAndroid Build Coastguard Worker ALOGD("channel '%s' ~ prepareDispatchCycle - flags=%s, "
3383*38e8c45fSAndroid Build Coastguard Worker "globalScaleFactor=%f, pointerIds=%s %s",
3384*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str(), inputTarget.flags.string().c_str(),
3385*38e8c45fSAndroid Build Coastguard Worker inputTarget.globalScaleFactor, bitsetToString(inputTarget.getPointerIds()).c_str(),
3386*38e8c45fSAndroid Build Coastguard Worker inputTarget.getPointerInfoString().c_str());
3387*38e8c45fSAndroid Build Coastguard Worker }
3388*38e8c45fSAndroid Build Coastguard Worker
3389*38e8c45fSAndroid Build Coastguard Worker // Skip this event if the connection status is not normal.
3390*38e8c45fSAndroid Build Coastguard Worker // We don't want to enqueue additional outbound events if the connection is broken.
3391*38e8c45fSAndroid Build Coastguard Worker if (connection->status != Connection::Status::NORMAL) {
3392*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_DISPATCH_CYCLE) {
3393*38e8c45fSAndroid Build Coastguard Worker ALOGD("channel '%s' ~ Dropping event because the channel status is %s",
3394*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str(),
3395*38e8c45fSAndroid Build Coastguard Worker ftl::enum_string(connection->status).c_str());
3396*38e8c45fSAndroid Build Coastguard Worker }
3397*38e8c45fSAndroid Build Coastguard Worker return;
3398*38e8c45fSAndroid Build Coastguard Worker }
3399*38e8c45fSAndroid Build Coastguard Worker
3400*38e8c45fSAndroid Build Coastguard Worker // Split a motion event if needed.
3401*38e8c45fSAndroid Build Coastguard Worker if (inputTarget.flags.test(InputTarget::Flags::SPLIT)) {
3402*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(eventEntry->type != EventEntry::Type::MOTION,
3403*38e8c45fSAndroid Build Coastguard Worker "Entry type %s should not have Flags::SPLIT",
3404*38e8c45fSAndroid Build Coastguard Worker ftl::enum_string(eventEntry->type).c_str());
3405*38e8c45fSAndroid Build Coastguard Worker
3406*38e8c45fSAndroid Build Coastguard Worker const MotionEntry& originalMotionEntry = static_cast<const MotionEntry&>(*eventEntry);
3407*38e8c45fSAndroid Build Coastguard Worker if (inputTarget.getPointerIds().count() != originalMotionEntry.getPointerCount()) {
3408*38e8c45fSAndroid Build Coastguard Worker if (!inputTarget.firstDownTimeInTarget.has_value()) {
3409*38e8c45fSAndroid Build Coastguard Worker logDispatchStateLocked();
3410*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << "Splitting motion events requires a down time to be set for the "
3411*38e8c45fSAndroid Build Coastguard Worker "target on connection "
3412*38e8c45fSAndroid Build Coastguard Worker << connection->getInputChannelName() << " for "
3413*38e8c45fSAndroid Build Coastguard Worker << originalMotionEntry.getDescription();
3414*38e8c45fSAndroid Build Coastguard Worker }
3415*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<MotionEntry> splitMotionEntry =
3416*38e8c45fSAndroid Build Coastguard Worker splitMotionEvent(originalMotionEntry, inputTarget.getPointerIds(),
3417*38e8c45fSAndroid Build Coastguard Worker inputTarget.firstDownTimeInTarget.value());
3418*38e8c45fSAndroid Build Coastguard Worker if (!splitMotionEntry) {
3419*38e8c45fSAndroid Build Coastguard Worker return; // split event was dropped
3420*38e8c45fSAndroid Build Coastguard Worker }
3421*38e8c45fSAndroid Build Coastguard Worker if (splitMotionEntry->action == AMOTION_EVENT_ACTION_CANCEL) {
3422*38e8c45fSAndroid Build Coastguard Worker std::string reason = std::string("reason=pointer cancel on split window");
3423*38e8c45fSAndroid Build Coastguard Worker android_log_event_list(LOGTAG_INPUT_CANCEL)
3424*38e8c45fSAndroid Build Coastguard Worker << connection->getInputChannelName().c_str() << reason << LOG_ID_EVENTS;
3425*38e8c45fSAndroid Build Coastguard Worker }
3426*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_FOCUS) {
3427*38e8c45fSAndroid Build Coastguard Worker ALOGD("channel '%s' ~ Split motion event.",
3428*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str());
3429*38e8c45fSAndroid Build Coastguard Worker logOutboundMotionDetails(" ", *splitMotionEntry);
3430*38e8c45fSAndroid Build Coastguard Worker }
3431*38e8c45fSAndroid Build Coastguard Worker enqueueDispatchEntryAndStartDispatchCycleLocked(currentTime, connection,
3432*38e8c45fSAndroid Build Coastguard Worker std::move(splitMotionEntry),
3433*38e8c45fSAndroid Build Coastguard Worker inputTarget);
3434*38e8c45fSAndroid Build Coastguard Worker return;
3435*38e8c45fSAndroid Build Coastguard Worker }
3436*38e8c45fSAndroid Build Coastguard Worker }
3437*38e8c45fSAndroid Build Coastguard Worker
3438*38e8c45fSAndroid Build Coastguard Worker // Not splitting. Enqueue dispatch entries for the event as is.
3439*38e8c45fSAndroid Build Coastguard Worker enqueueDispatchEntryAndStartDispatchCycleLocked(currentTime, connection, eventEntry,
3440*38e8c45fSAndroid Build Coastguard Worker inputTarget);
3441*38e8c45fSAndroid Build Coastguard Worker }
3442*38e8c45fSAndroid Build Coastguard Worker
enqueueDispatchEntryAndStartDispatchCycleLocked(nsecs_t currentTime,const std::shared_ptr<Connection> & connection,std::shared_ptr<const EventEntry> eventEntry,const InputTarget & inputTarget)3443*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::enqueueDispatchEntryAndStartDispatchCycleLocked(
3444*38e8c45fSAndroid Build Coastguard Worker nsecs_t currentTime, const std::shared_ptr<Connection>& connection,
3445*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const EventEntry> eventEntry, const InputTarget& inputTarget) {
3446*38e8c45fSAndroid Build Coastguard Worker ATRACE_NAME_IF(ATRACE_ENABLED(),
3447*38e8c45fSAndroid Build Coastguard Worker StringPrintf("enqueueDispatchEntryAndStartDispatchCycleLocked(inputChannel=%s, "
3448*38e8c45fSAndroid Build Coastguard Worker "id=0x%" PRIx32 ")",
3449*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str(), eventEntry->id));
3450*38e8c45fSAndroid Build Coastguard Worker
3451*38e8c45fSAndroid Build Coastguard Worker const bool wasEmpty = connection->outboundQueue.empty();
3452*38e8c45fSAndroid Build Coastguard Worker
3453*38e8c45fSAndroid Build Coastguard Worker enqueueDispatchEntryLocked(connection, eventEntry, inputTarget);
3454*38e8c45fSAndroid Build Coastguard Worker
3455*38e8c45fSAndroid Build Coastguard Worker // If the outbound queue was previously empty, start the dispatch cycle going.
3456*38e8c45fSAndroid Build Coastguard Worker if (wasEmpty && !connection->outboundQueue.empty()) {
3457*38e8c45fSAndroid Build Coastguard Worker startDispatchCycleLocked(currentTime, connection);
3458*38e8c45fSAndroid Build Coastguard Worker }
3459*38e8c45fSAndroid Build Coastguard Worker }
3460*38e8c45fSAndroid Build Coastguard Worker
enqueueDispatchEntryLocked(const std::shared_ptr<Connection> & connection,std::shared_ptr<const EventEntry> eventEntry,const InputTarget & inputTarget)3461*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::enqueueDispatchEntryLocked(const std::shared_ptr<Connection>& connection,
3462*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const EventEntry> eventEntry,
3463*38e8c45fSAndroid Build Coastguard Worker const InputTarget& inputTarget) {
3464*38e8c45fSAndroid Build Coastguard Worker const bool isKeyOrMotion = eventEntry->type == EventEntry::Type::KEY ||
3465*38e8c45fSAndroid Build Coastguard Worker eventEntry->type == EventEntry::Type::MOTION;
3466*38e8c45fSAndroid Build Coastguard Worker if (isKeyOrMotion && !inputTarget.windowHandle && !connection->monitor) {
3467*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << "All InputTargets for non-monitors must be associated with a window; target: "
3468*38e8c45fSAndroid Build Coastguard Worker << inputTarget << " connection: " << connection->getInputChannelName()
3469*38e8c45fSAndroid Build Coastguard Worker << " entry: " << eventEntry->getDescription();
3470*38e8c45fSAndroid Build Coastguard Worker }
3471*38e8c45fSAndroid Build Coastguard Worker // This is a new event.
3472*38e8c45fSAndroid Build Coastguard Worker // Enqueue a new dispatch entry onto the outbound queue for this connection.
3473*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<DispatchEntry> dispatchEntry =
3474*38e8c45fSAndroid Build Coastguard Worker createDispatchEntry(mIdGenerator, inputTarget, eventEntry, inputTarget.flags,
3475*38e8c45fSAndroid Build Coastguard Worker mWindowInfosVsyncId, mTracer.get());
3476*38e8c45fSAndroid Build Coastguard Worker
3477*38e8c45fSAndroid Build Coastguard Worker // Use the eventEntry from dispatchEntry since the entry may have changed and can now be a
3478*38e8c45fSAndroid Build Coastguard Worker // different EventEntry than what was passed in.
3479*38e8c45fSAndroid Build Coastguard Worker eventEntry = dispatchEntry->eventEntry;
3480*38e8c45fSAndroid Build Coastguard Worker // Apply target flags and update the connection's input state.
3481*38e8c45fSAndroid Build Coastguard Worker switch (eventEntry->type) {
3482*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::KEY: {
3483*38e8c45fSAndroid Build Coastguard Worker const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*eventEntry);
3484*38e8c45fSAndroid Build Coastguard Worker if (!connection->inputState.trackKey(keyEntry, keyEntry.flags)) {
3485*38e8c45fSAndroid Build Coastguard Worker LOG(WARNING) << "channel " << connection->getInputChannelName()
3486*38e8c45fSAndroid Build Coastguard Worker << "~ dropping inconsistent event: " << *dispatchEntry;
3487*38e8c45fSAndroid Build Coastguard Worker return; // skip the inconsistent event
3488*38e8c45fSAndroid Build Coastguard Worker }
3489*38e8c45fSAndroid Build Coastguard Worker break;
3490*38e8c45fSAndroid Build Coastguard Worker }
3491*38e8c45fSAndroid Build Coastguard Worker
3492*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::MOTION: {
3493*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const MotionEntry> resolvedMotion =
3494*38e8c45fSAndroid Build Coastguard Worker std::static_pointer_cast<const MotionEntry>(eventEntry);
3495*38e8c45fSAndroid Build Coastguard Worker {
3496*38e8c45fSAndroid Build Coastguard Worker // Determine the resolved motion entry.
3497*38e8c45fSAndroid Build Coastguard Worker const MotionEntry& motionEntry = static_cast<const MotionEntry&>(*eventEntry);
3498*38e8c45fSAndroid Build Coastguard Worker int32_t resolvedAction = motionEntry.action;
3499*38e8c45fSAndroid Build Coastguard Worker int32_t resolvedFlags = motionEntry.flags;
3500*38e8c45fSAndroid Build Coastguard Worker
3501*38e8c45fSAndroid Build Coastguard Worker if (inputTarget.dispatchMode == InputTarget::DispatchMode::OUTSIDE) {
3502*38e8c45fSAndroid Build Coastguard Worker resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE;
3503*38e8c45fSAndroid Build Coastguard Worker } else if (inputTarget.dispatchMode == InputTarget::DispatchMode::HOVER_EXIT) {
3504*38e8c45fSAndroid Build Coastguard Worker resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT;
3505*38e8c45fSAndroid Build Coastguard Worker } else if (inputTarget.dispatchMode == InputTarget::DispatchMode::HOVER_ENTER) {
3506*38e8c45fSAndroid Build Coastguard Worker resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
3507*38e8c45fSAndroid Build Coastguard Worker } else if (inputTarget.dispatchMode == InputTarget::DispatchMode::SLIPPERY_EXIT) {
3508*38e8c45fSAndroid Build Coastguard Worker resolvedAction = AMOTION_EVENT_ACTION_CANCEL;
3509*38e8c45fSAndroid Build Coastguard Worker } else if (inputTarget.dispatchMode == InputTarget::DispatchMode::SLIPPERY_ENTER) {
3510*38e8c45fSAndroid Build Coastguard Worker resolvedAction = AMOTION_EVENT_ACTION_DOWN;
3511*38e8c45fSAndroid Build Coastguard Worker }
3512*38e8c45fSAndroid Build Coastguard Worker if (resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE &&
3513*38e8c45fSAndroid Build Coastguard Worker !connection->inputState.isHovering(motionEntry.deviceId, motionEntry.source,
3514*38e8c45fSAndroid Build Coastguard Worker motionEntry.displayId)) {
3515*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_DISPATCH_CYCLE) {
3516*38e8c45fSAndroid Build Coastguard Worker LOG(DEBUG) << "channel '" << connection->getInputChannelName().c_str()
3517*38e8c45fSAndroid Build Coastguard Worker << "' ~ enqueueDispatchEntryLocked: filling in missing hover "
3518*38e8c45fSAndroid Build Coastguard Worker "enter event";
3519*38e8c45fSAndroid Build Coastguard Worker }
3520*38e8c45fSAndroid Build Coastguard Worker resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
3521*38e8c45fSAndroid Build Coastguard Worker }
3522*38e8c45fSAndroid Build Coastguard Worker
3523*38e8c45fSAndroid Build Coastguard Worker if (resolvedAction == AMOTION_EVENT_ACTION_CANCEL) {
3524*38e8c45fSAndroid Build Coastguard Worker resolvedFlags |= AMOTION_EVENT_FLAG_CANCELED;
3525*38e8c45fSAndroid Build Coastguard Worker }
3526*38e8c45fSAndroid Build Coastguard Worker if (dispatchEntry->targetFlags.test(InputTarget::Flags::WINDOW_IS_OBSCURED)) {
3527*38e8c45fSAndroid Build Coastguard Worker resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
3528*38e8c45fSAndroid Build Coastguard Worker }
3529*38e8c45fSAndroid Build Coastguard Worker if (dispatchEntry->targetFlags.test(
3530*38e8c45fSAndroid Build Coastguard Worker InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED)) {
3531*38e8c45fSAndroid Build Coastguard Worker resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
3532*38e8c45fSAndroid Build Coastguard Worker }
3533*38e8c45fSAndroid Build Coastguard Worker if (dispatchEntry->targetFlags.test(InputTarget::Flags::NO_FOCUS_CHANGE)) {
3534*38e8c45fSAndroid Build Coastguard Worker resolvedFlags |= AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE;
3535*38e8c45fSAndroid Build Coastguard Worker }
3536*38e8c45fSAndroid Build Coastguard Worker
3537*38e8c45fSAndroid Build Coastguard Worker dispatchEntry->resolvedFlags = resolvedFlags;
3538*38e8c45fSAndroid Build Coastguard Worker if (resolvedAction != motionEntry.action) {
3539*38e8c45fSAndroid Build Coastguard Worker std::optional<std::vector<PointerProperties>> usingProperties;
3540*38e8c45fSAndroid Build Coastguard Worker std::optional<std::vector<PointerCoords>> usingCoords;
3541*38e8c45fSAndroid Build Coastguard Worker if (resolvedAction == AMOTION_EVENT_ACTION_HOVER_EXIT ||
3542*38e8c45fSAndroid Build Coastguard Worker resolvedAction == AMOTION_EVENT_ACTION_CANCEL) {
3543*38e8c45fSAndroid Build Coastguard Worker // This is a HOVER_EXIT or an ACTION_CANCEL event that was synthesized by
3544*38e8c45fSAndroid Build Coastguard Worker // the dispatcher, and therefore the coordinates of this event are currently
3545*38e8c45fSAndroid Build Coastguard Worker // incorrect. These events should use the coordinates of the last dispatched
3546*38e8c45fSAndroid Build Coastguard Worker // ACTION_MOVE or HOVER_MOVE. We need to query InputState to get this data.
3547*38e8c45fSAndroid Build Coastguard Worker const bool hovering = resolvedAction == AMOTION_EVENT_ACTION_HOVER_EXIT;
3548*38e8c45fSAndroid Build Coastguard Worker std::optional<std::pair<std::vector<PointerProperties>,
3549*38e8c45fSAndroid Build Coastguard Worker std::vector<PointerCoords>>>
3550*38e8c45fSAndroid Build Coastguard Worker pointerInfo =
3551*38e8c45fSAndroid Build Coastguard Worker connection->inputState.getPointersOfLastEvent(motionEntry,
3552*38e8c45fSAndroid Build Coastguard Worker hovering);
3553*38e8c45fSAndroid Build Coastguard Worker if (pointerInfo) {
3554*38e8c45fSAndroid Build Coastguard Worker usingProperties = pointerInfo->first;
3555*38e8c45fSAndroid Build Coastguard Worker usingCoords = pointerInfo->second;
3556*38e8c45fSAndroid Build Coastguard Worker }
3557*38e8c45fSAndroid Build Coastguard Worker }
3558*38e8c45fSAndroid Build Coastguard Worker {
3559*38e8c45fSAndroid Build Coastguard Worker // Generate a new MotionEntry with a new eventId using the resolved action
3560*38e8c45fSAndroid Build Coastguard Worker // and flags, and set it as the resolved entry.
3561*38e8c45fSAndroid Build Coastguard Worker auto newEntry = std::make_shared<
3562*38e8c45fSAndroid Build Coastguard Worker MotionEntry>(mIdGenerator.nextId(), motionEntry.injectionState,
3563*38e8c45fSAndroid Build Coastguard Worker motionEntry.eventTime, motionEntry.deviceId,
3564*38e8c45fSAndroid Build Coastguard Worker motionEntry.source, motionEntry.displayId,
3565*38e8c45fSAndroid Build Coastguard Worker motionEntry.policyFlags, resolvedAction,
3566*38e8c45fSAndroid Build Coastguard Worker motionEntry.actionButton, resolvedFlags,
3567*38e8c45fSAndroid Build Coastguard Worker motionEntry.metaState, motionEntry.buttonState,
3568*38e8c45fSAndroid Build Coastguard Worker motionEntry.classification, motionEntry.edgeFlags,
3569*38e8c45fSAndroid Build Coastguard Worker motionEntry.xPrecision, motionEntry.yPrecision,
3570*38e8c45fSAndroid Build Coastguard Worker motionEntry.xCursorPosition,
3571*38e8c45fSAndroid Build Coastguard Worker motionEntry.yCursorPosition, motionEntry.downTime,
3572*38e8c45fSAndroid Build Coastguard Worker usingProperties.value_or(
3573*38e8c45fSAndroid Build Coastguard Worker motionEntry.pointerProperties),
3574*38e8c45fSAndroid Build Coastguard Worker usingCoords.value_or(motionEntry.pointerCoords));
3575*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
3576*38e8c45fSAndroid Build Coastguard Worker ensureEventTraced(motionEntry);
3577*38e8c45fSAndroid Build Coastguard Worker newEntry->traceTracker =
3578*38e8c45fSAndroid Build Coastguard Worker mTracer->traceDerivedEvent(*newEntry,
3579*38e8c45fSAndroid Build Coastguard Worker *motionEntry.traceTracker);
3580*38e8c45fSAndroid Build Coastguard Worker }
3581*38e8c45fSAndroid Build Coastguard Worker resolvedMotion = newEntry;
3582*38e8c45fSAndroid Build Coastguard Worker }
3583*38e8c45fSAndroid Build Coastguard Worker if (ATRACE_ENABLED()) {
3584*38e8c45fSAndroid Build Coastguard Worker std::string message = StringPrintf("Transmute MotionEvent(id=0x%" PRIx32
3585*38e8c45fSAndroid Build Coastguard Worker ") to MotionEvent(id=0x%" PRIx32 ").",
3586*38e8c45fSAndroid Build Coastguard Worker motionEntry.id, resolvedMotion->id);
3587*38e8c45fSAndroid Build Coastguard Worker ATRACE_NAME(message.c_str());
3588*38e8c45fSAndroid Build Coastguard Worker }
3589*38e8c45fSAndroid Build Coastguard Worker
3590*38e8c45fSAndroid Build Coastguard Worker // Set the resolved motion entry in the DispatchEntry.
3591*38e8c45fSAndroid Build Coastguard Worker dispatchEntry->eventEntry = resolvedMotion;
3592*38e8c45fSAndroid Build Coastguard Worker eventEntry = resolvedMotion;
3593*38e8c45fSAndroid Build Coastguard Worker }
3594*38e8c45fSAndroid Build Coastguard Worker }
3595*38e8c45fSAndroid Build Coastguard Worker
3596*38e8c45fSAndroid Build Coastguard Worker // Check if we need to cancel any of the ongoing gestures. We don't support multiple
3597*38e8c45fSAndroid Build Coastguard Worker // devices being active at the same time in the same window, so if a new device is
3598*38e8c45fSAndroid Build Coastguard Worker // active, cancel the gesture from the old device.
3599*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<EventEntry> cancelEvent =
3600*38e8c45fSAndroid Build Coastguard Worker connection->inputState.cancelConflictingInputStream(*resolvedMotion);
3601*38e8c45fSAndroid Build Coastguard Worker if (cancelEvent != nullptr) {
3602*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "Canceling pointers for device " << resolvedMotion->deviceId << " in "
3603*38e8c45fSAndroid Build Coastguard Worker << connection->getInputChannelName() << " with event "
3604*38e8c45fSAndroid Build Coastguard Worker << cancelEvent->getDescription();
3605*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
3606*38e8c45fSAndroid Build Coastguard Worker static_cast<MotionEntry&>(*cancelEvent).traceTracker =
3607*38e8c45fSAndroid Build Coastguard Worker mTracer->traceDerivedEvent(*cancelEvent, *resolvedMotion->traceTracker);
3608*38e8c45fSAndroid Build Coastguard Worker }
3609*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<DispatchEntry> cancelDispatchEntry =
3610*38e8c45fSAndroid Build Coastguard Worker createDispatchEntry(mIdGenerator, inputTarget, std::move(cancelEvent),
3611*38e8c45fSAndroid Build Coastguard Worker ftl::Flags<InputTarget::Flags>(), mWindowInfosVsyncId,
3612*38e8c45fSAndroid Build Coastguard Worker mTracer.get());
3613*38e8c45fSAndroid Build Coastguard Worker
3614*38e8c45fSAndroid Build Coastguard Worker // Send these cancel events to the queue before sending the event from the new
3615*38e8c45fSAndroid Build Coastguard Worker // device.
3616*38e8c45fSAndroid Build Coastguard Worker connection->outboundQueue.emplace_back(std::move(cancelDispatchEntry));
3617*38e8c45fSAndroid Build Coastguard Worker }
3618*38e8c45fSAndroid Build Coastguard Worker
3619*38e8c45fSAndroid Build Coastguard Worker if (!connection->inputState.trackMotion(*resolvedMotion,
3620*38e8c45fSAndroid Build Coastguard Worker dispatchEntry->resolvedFlags)) {
3621*38e8c45fSAndroid Build Coastguard Worker LOG(WARNING) << "channel " << connection->getInputChannelName()
3622*38e8c45fSAndroid Build Coastguard Worker << "~ dropping inconsistent event: " << *dispatchEntry;
3623*38e8c45fSAndroid Build Coastguard Worker return; // skip the inconsistent event
3624*38e8c45fSAndroid Build Coastguard Worker }
3625*38e8c45fSAndroid Build Coastguard Worker if ((dispatchEntry->resolvedFlags & AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE) &&
3626*38e8c45fSAndroid Build Coastguard Worker (resolvedMotion->policyFlags & POLICY_FLAG_TRUSTED)) {
3627*38e8c45fSAndroid Build Coastguard Worker // Skip reporting pointer down outside focus to the policy.
3628*38e8c45fSAndroid Build Coastguard Worker break;
3629*38e8c45fSAndroid Build Coastguard Worker }
3630*38e8c45fSAndroid Build Coastguard Worker
3631*38e8c45fSAndroid Build Coastguard Worker dispatchPointerDownOutsideFocus(resolvedMotion->source, resolvedMotion->action,
3632*38e8c45fSAndroid Build Coastguard Worker inputTarget.connection->getToken());
3633*38e8c45fSAndroid Build Coastguard Worker
3634*38e8c45fSAndroid Build Coastguard Worker break;
3635*38e8c45fSAndroid Build Coastguard Worker }
3636*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::FOCUS:
3637*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::TOUCH_MODE_CHANGED:
3638*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::POINTER_CAPTURE_CHANGED:
3639*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::DRAG: {
3640*38e8c45fSAndroid Build Coastguard Worker break;
3641*38e8c45fSAndroid Build Coastguard Worker }
3642*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::SENSOR: {
3643*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("SENSOR events should not go to apps via input channel");
3644*38e8c45fSAndroid Build Coastguard Worker break;
3645*38e8c45fSAndroid Build Coastguard Worker }
3646*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::DEVICE_RESET: {
3647*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("%s events should not go to apps",
3648*38e8c45fSAndroid Build Coastguard Worker ftl::enum_string(eventEntry->type).c_str());
3649*38e8c45fSAndroid Build Coastguard Worker break;
3650*38e8c45fSAndroid Build Coastguard Worker }
3651*38e8c45fSAndroid Build Coastguard Worker }
3652*38e8c45fSAndroid Build Coastguard Worker
3653*38e8c45fSAndroid Build Coastguard Worker // Remember that we are waiting for this dispatch to complete.
3654*38e8c45fSAndroid Build Coastguard Worker if (dispatchEntry->hasForegroundTarget()) {
3655*38e8c45fSAndroid Build Coastguard Worker incrementPendingForegroundDispatches(*eventEntry);
3656*38e8c45fSAndroid Build Coastguard Worker }
3657*38e8c45fSAndroid Build Coastguard Worker
3658*38e8c45fSAndroid Build Coastguard Worker // Enqueue the dispatch entry.
3659*38e8c45fSAndroid Build Coastguard Worker connection->outboundQueue.emplace_back(std::move(dispatchEntry));
3660*38e8c45fSAndroid Build Coastguard Worker traceOutboundQueueLength(*connection);
3661*38e8c45fSAndroid Build Coastguard Worker }
3662*38e8c45fSAndroid Build Coastguard Worker
3663*38e8c45fSAndroid Build Coastguard Worker /**
3664*38e8c45fSAndroid Build Coastguard Worker * This function is for debugging and metrics collection. It has two roles.
3665*38e8c45fSAndroid Build Coastguard Worker *
3666*38e8c45fSAndroid Build Coastguard Worker * The first role is to log input interaction with windows, which helps determine what the user was
3667*38e8c45fSAndroid Build Coastguard Worker * interacting with. For example, if user is touching launcher, we will see an input_interaction log
3668*38e8c45fSAndroid Build Coastguard Worker * that user started interacting with launcher window, as well as any other window that received
3669*38e8c45fSAndroid Build Coastguard Worker * that gesture, such as the wallpaper or other spy windows. A new input_interaction is only logged
3670*38e8c45fSAndroid Build Coastguard Worker * when the set of tokens that received the event changes. It is not logged again as long as the
3671*38e8c45fSAndroid Build Coastguard Worker * user is interacting with the same windows.
3672*38e8c45fSAndroid Build Coastguard Worker *
3673*38e8c45fSAndroid Build Coastguard Worker * The second role is to track input device activity for metrics collection. For each input event,
3674*38e8c45fSAndroid Build Coastguard Worker * we report the set of UIDs that the input device interacted with to the policy. Unlike for the
3675*38e8c45fSAndroid Build Coastguard Worker * input_interaction logs, the device interaction is reported even when the set of interaction
3676*38e8c45fSAndroid Build Coastguard Worker * tokens do not change.
3677*38e8c45fSAndroid Build Coastguard Worker *
3678*38e8c45fSAndroid Build Coastguard Worker * For these purposes, we do not count ACTION_OUTSIDE, ACTION_UP and ACTION_CANCEL actions as
3679*38e8c45fSAndroid Build Coastguard Worker * interaction. This includes up and cancel events for both keys and motions.
3680*38e8c45fSAndroid Build Coastguard Worker */
processInteractionsLocked(const EventEntry & entry,const std::vector<InputTarget> & targets)3681*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::processInteractionsLocked(const EventEntry& entry,
3682*38e8c45fSAndroid Build Coastguard Worker const std::vector<InputTarget>& targets) {
3683*38e8c45fSAndroid Build Coastguard Worker int32_t deviceId;
3684*38e8c45fSAndroid Build Coastguard Worker nsecs_t eventTime;
3685*38e8c45fSAndroid Build Coastguard Worker // Skip ACTION_UP events, and all events other than keys and motions
3686*38e8c45fSAndroid Build Coastguard Worker if (entry.type == EventEntry::Type::KEY) {
3687*38e8c45fSAndroid Build Coastguard Worker const KeyEntry& keyEntry = static_cast<const KeyEntry&>(entry);
3688*38e8c45fSAndroid Build Coastguard Worker if (keyEntry.action == AKEY_EVENT_ACTION_UP) {
3689*38e8c45fSAndroid Build Coastguard Worker return;
3690*38e8c45fSAndroid Build Coastguard Worker }
3691*38e8c45fSAndroid Build Coastguard Worker deviceId = keyEntry.deviceId;
3692*38e8c45fSAndroid Build Coastguard Worker eventTime = keyEntry.eventTime;
3693*38e8c45fSAndroid Build Coastguard Worker } else if (entry.type == EventEntry::Type::MOTION) {
3694*38e8c45fSAndroid Build Coastguard Worker const MotionEntry& motionEntry = static_cast<const MotionEntry&>(entry);
3695*38e8c45fSAndroid Build Coastguard Worker if (motionEntry.action == AMOTION_EVENT_ACTION_UP ||
3696*38e8c45fSAndroid Build Coastguard Worker motionEntry.action == AMOTION_EVENT_ACTION_CANCEL ||
3697*38e8c45fSAndroid Build Coastguard Worker MotionEvent::getActionMasked(motionEntry.action) == AMOTION_EVENT_ACTION_POINTER_UP) {
3698*38e8c45fSAndroid Build Coastguard Worker return;
3699*38e8c45fSAndroid Build Coastguard Worker }
3700*38e8c45fSAndroid Build Coastguard Worker deviceId = motionEntry.deviceId;
3701*38e8c45fSAndroid Build Coastguard Worker eventTime = motionEntry.eventTime;
3702*38e8c45fSAndroid Build Coastguard Worker } else {
3703*38e8c45fSAndroid Build Coastguard Worker return; // Not a key or a motion
3704*38e8c45fSAndroid Build Coastguard Worker }
3705*38e8c45fSAndroid Build Coastguard Worker
3706*38e8c45fSAndroid Build Coastguard Worker std::set<gui::Uid> interactionUids;
3707*38e8c45fSAndroid Build Coastguard Worker std::unordered_set<sp<IBinder>, StrongPointerHash<IBinder>> newConnectionTokens;
3708*38e8c45fSAndroid Build Coastguard Worker std::vector<std::shared_ptr<Connection>> newConnections;
3709*38e8c45fSAndroid Build Coastguard Worker for (const InputTarget& target : targets) {
3710*38e8c45fSAndroid Build Coastguard Worker if (target.dispatchMode == InputTarget::DispatchMode::OUTSIDE) {
3711*38e8c45fSAndroid Build Coastguard Worker continue; // Skip windows that receive ACTION_OUTSIDE
3712*38e8c45fSAndroid Build Coastguard Worker }
3713*38e8c45fSAndroid Build Coastguard Worker
3714*38e8c45fSAndroid Build Coastguard Worker sp<IBinder> token = target.connection->getToken();
3715*38e8c45fSAndroid Build Coastguard Worker newConnectionTokens.insert(std::move(token));
3716*38e8c45fSAndroid Build Coastguard Worker newConnections.emplace_back(target.connection);
3717*38e8c45fSAndroid Build Coastguard Worker if (target.windowHandle) {
3718*38e8c45fSAndroid Build Coastguard Worker interactionUids.emplace(target.windowHandle->getInfo()->ownerUid);
3719*38e8c45fSAndroid Build Coastguard Worker }
3720*38e8c45fSAndroid Build Coastguard Worker }
3721*38e8c45fSAndroid Build Coastguard Worker
3722*38e8c45fSAndroid Build Coastguard Worker auto command = [this, deviceId, eventTime, uids = std::move(interactionUids)]()
3723*38e8c45fSAndroid Build Coastguard Worker REQUIRES(mLock) {
3724*38e8c45fSAndroid Build Coastguard Worker scoped_unlock unlock(mLock);
3725*38e8c45fSAndroid Build Coastguard Worker mPolicy.notifyDeviceInteraction(deviceId, eventTime, uids);
3726*38e8c45fSAndroid Build Coastguard Worker };
3727*38e8c45fSAndroid Build Coastguard Worker postCommandLocked(std::move(command));
3728*38e8c45fSAndroid Build Coastguard Worker
3729*38e8c45fSAndroid Build Coastguard Worker if (newConnectionTokens == mInteractionConnectionTokens) {
3730*38e8c45fSAndroid Build Coastguard Worker return; // no change
3731*38e8c45fSAndroid Build Coastguard Worker }
3732*38e8c45fSAndroid Build Coastguard Worker mInteractionConnectionTokens = newConnectionTokens;
3733*38e8c45fSAndroid Build Coastguard Worker
3734*38e8c45fSAndroid Build Coastguard Worker std::string targetList;
3735*38e8c45fSAndroid Build Coastguard Worker for (const std::shared_ptr<Connection>& connection : newConnections) {
3736*38e8c45fSAndroid Build Coastguard Worker targetList += connection->getInputChannelName() + ", ";
3737*38e8c45fSAndroid Build Coastguard Worker }
3738*38e8c45fSAndroid Build Coastguard Worker std::string message = "Interaction with: " + targetList;
3739*38e8c45fSAndroid Build Coastguard Worker if (targetList.empty()) {
3740*38e8c45fSAndroid Build Coastguard Worker message += "<none>";
3741*38e8c45fSAndroid Build Coastguard Worker }
3742*38e8c45fSAndroid Build Coastguard Worker android_log_event_list(LOGTAG_INPUT_INTERACTION) << message << LOG_ID_EVENTS;
3743*38e8c45fSAndroid Build Coastguard Worker }
3744*38e8c45fSAndroid Build Coastguard Worker
dispatchPointerDownOutsideFocus(uint32_t source,int32_t action,const sp<IBinder> & token)3745*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::dispatchPointerDownOutsideFocus(uint32_t source, int32_t action,
3746*38e8c45fSAndroid Build Coastguard Worker const sp<IBinder>& token) {
3747*38e8c45fSAndroid Build Coastguard Worker int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
3748*38e8c45fSAndroid Build Coastguard Worker uint32_t maskedSource = source & AINPUT_SOURCE_CLASS_MASK;
3749*38e8c45fSAndroid Build Coastguard Worker if (maskedSource != AINPUT_SOURCE_CLASS_POINTER || maskedAction != AMOTION_EVENT_ACTION_DOWN) {
3750*38e8c45fSAndroid Build Coastguard Worker return;
3751*38e8c45fSAndroid Build Coastguard Worker }
3752*38e8c45fSAndroid Build Coastguard Worker
3753*38e8c45fSAndroid Build Coastguard Worker sp<IBinder> focusedToken = mFocusResolver.getFocusedWindowToken(mFocusedDisplayId);
3754*38e8c45fSAndroid Build Coastguard Worker if (focusedToken == token) {
3755*38e8c45fSAndroid Build Coastguard Worker // ignore since token is focused
3756*38e8c45fSAndroid Build Coastguard Worker return;
3757*38e8c45fSAndroid Build Coastguard Worker }
3758*38e8c45fSAndroid Build Coastguard Worker
3759*38e8c45fSAndroid Build Coastguard Worker auto command = [this, token]() REQUIRES(mLock) {
3760*38e8c45fSAndroid Build Coastguard Worker scoped_unlock unlock(mLock);
3761*38e8c45fSAndroid Build Coastguard Worker mPolicy.onPointerDownOutsideFocus(token);
3762*38e8c45fSAndroid Build Coastguard Worker };
3763*38e8c45fSAndroid Build Coastguard Worker postCommandLocked(std::move(command));
3764*38e8c45fSAndroid Build Coastguard Worker }
3765*38e8c45fSAndroid Build Coastguard Worker
publishMotionEvent(Connection & connection,DispatchEntry & dispatchEntry) const3766*38e8c45fSAndroid Build Coastguard Worker status_t InputDispatcher::publishMotionEvent(Connection& connection,
3767*38e8c45fSAndroid Build Coastguard Worker DispatchEntry& dispatchEntry) const {
3768*38e8c45fSAndroid Build Coastguard Worker const EventEntry& eventEntry = *(dispatchEntry.eventEntry);
3769*38e8c45fSAndroid Build Coastguard Worker const MotionEntry& motionEntry = static_cast<const MotionEntry&>(eventEntry);
3770*38e8c45fSAndroid Build Coastguard Worker
3771*38e8c45fSAndroid Build Coastguard Worker PointerCoords scaledCoords[MAX_POINTERS];
3772*38e8c45fSAndroid Build Coastguard Worker const PointerCoords* usingCoords = motionEntry.pointerCoords.data();
3773*38e8c45fSAndroid Build Coastguard Worker
3774*38e8c45fSAndroid Build Coastguard Worker // TODO(b/316355518): Do not modify coords before dispatch.
3775*38e8c45fSAndroid Build Coastguard Worker // Set the X and Y offset and X and Y scale depending on the input source.
3776*38e8c45fSAndroid Build Coastguard Worker if ((motionEntry.source & AINPUT_SOURCE_CLASS_POINTER) &&
3777*38e8c45fSAndroid Build Coastguard Worker !(dispatchEntry.targetFlags.test(InputTarget::Flags::ZERO_COORDS))) {
3778*38e8c45fSAndroid Build Coastguard Worker float globalScaleFactor = dispatchEntry.globalScaleFactor;
3779*38e8c45fSAndroid Build Coastguard Worker if (globalScaleFactor != 1.0f) {
3780*38e8c45fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < motionEntry.getPointerCount(); i++) {
3781*38e8c45fSAndroid Build Coastguard Worker scaledCoords[i] = motionEntry.pointerCoords[i];
3782*38e8c45fSAndroid Build Coastguard Worker // Don't apply window scale here since we don't want scale to affect raw
3783*38e8c45fSAndroid Build Coastguard Worker // coordinates. The scale will be sent back to the client and applied
3784*38e8c45fSAndroid Build Coastguard Worker // later when requesting relative coordinates.
3785*38e8c45fSAndroid Build Coastguard Worker scaledCoords[i].scale(globalScaleFactor, /*windowXScale=*/1, /*windowYScale=*/1);
3786*38e8c45fSAndroid Build Coastguard Worker }
3787*38e8c45fSAndroid Build Coastguard Worker usingCoords = scaledCoords;
3788*38e8c45fSAndroid Build Coastguard Worker }
3789*38e8c45fSAndroid Build Coastguard Worker }
3790*38e8c45fSAndroid Build Coastguard Worker
3791*38e8c45fSAndroid Build Coastguard Worker std::array<uint8_t, 32> hmac = getSignature(motionEntry, dispatchEntry);
3792*38e8c45fSAndroid Build Coastguard Worker
3793*38e8c45fSAndroid Build Coastguard Worker // Publish the motion event.
3794*38e8c45fSAndroid Build Coastguard Worker return connection.inputPublisher
3795*38e8c45fSAndroid Build Coastguard Worker .publishMotionEvent(dispatchEntry.seq, motionEntry.id, motionEntry.deviceId,
3796*38e8c45fSAndroid Build Coastguard Worker motionEntry.source, motionEntry.displayId, std::move(hmac),
3797*38e8c45fSAndroid Build Coastguard Worker motionEntry.action, motionEntry.actionButton,
3798*38e8c45fSAndroid Build Coastguard Worker dispatchEntry.resolvedFlags, motionEntry.edgeFlags,
3799*38e8c45fSAndroid Build Coastguard Worker motionEntry.metaState, motionEntry.buttonState,
3800*38e8c45fSAndroid Build Coastguard Worker motionEntry.classification, dispatchEntry.transform,
3801*38e8c45fSAndroid Build Coastguard Worker motionEntry.xPrecision, motionEntry.yPrecision,
3802*38e8c45fSAndroid Build Coastguard Worker motionEntry.xCursorPosition, motionEntry.yCursorPosition,
3803*38e8c45fSAndroid Build Coastguard Worker dispatchEntry.rawTransform, motionEntry.downTime,
3804*38e8c45fSAndroid Build Coastguard Worker motionEntry.eventTime, motionEntry.getPointerCount(),
3805*38e8c45fSAndroid Build Coastguard Worker motionEntry.pointerProperties.data(), usingCoords);
3806*38e8c45fSAndroid Build Coastguard Worker }
3807*38e8c45fSAndroid Build Coastguard Worker
startDispatchCycleLocked(nsecs_t currentTime,const std::shared_ptr<Connection> & connection)3808*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
3809*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<Connection>& connection) {
3810*38e8c45fSAndroid Build Coastguard Worker ATRACE_NAME_IF(ATRACE_ENABLED(),
3811*38e8c45fSAndroid Build Coastguard Worker StringPrintf("startDispatchCycleLocked(inputChannel=%s)",
3812*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str()));
3813*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_DISPATCH_CYCLE) {
3814*38e8c45fSAndroid Build Coastguard Worker ALOGD("channel '%s' ~ startDispatchCycle", connection->getInputChannelName().c_str());
3815*38e8c45fSAndroid Build Coastguard Worker }
3816*38e8c45fSAndroid Build Coastguard Worker
3817*38e8c45fSAndroid Build Coastguard Worker while (connection->status == Connection::Status::NORMAL && !connection->outboundQueue.empty()) {
3818*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<DispatchEntry>& dispatchEntry = connection->outboundQueue.front();
3819*38e8c45fSAndroid Build Coastguard Worker dispatchEntry->deliveryTime = currentTime;
3820*38e8c45fSAndroid Build Coastguard Worker const std::chrono::nanoseconds timeout = getDispatchingTimeoutLocked(connection);
3821*38e8c45fSAndroid Build Coastguard Worker dispatchEntry->timeoutTime = currentTime + timeout.count();
3822*38e8c45fSAndroid Build Coastguard Worker
3823*38e8c45fSAndroid Build Coastguard Worker // Publish the event.
3824*38e8c45fSAndroid Build Coastguard Worker status_t status;
3825*38e8c45fSAndroid Build Coastguard Worker const EventEntry& eventEntry = *(dispatchEntry->eventEntry);
3826*38e8c45fSAndroid Build Coastguard Worker switch (eventEntry.type) {
3827*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::KEY: {
3828*38e8c45fSAndroid Build Coastguard Worker const KeyEntry& keyEntry = static_cast<const KeyEntry&>(eventEntry);
3829*38e8c45fSAndroid Build Coastguard Worker std::array<uint8_t, 32> hmac = getSignature(keyEntry, *dispatchEntry);
3830*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_OUTBOUND_EVENT_DETAILS) {
3831*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "Publishing " << *dispatchEntry << " to "
3832*38e8c45fSAndroid Build Coastguard Worker << connection->getInputChannelName();
3833*38e8c45fSAndroid Build Coastguard Worker }
3834*38e8c45fSAndroid Build Coastguard Worker
3835*38e8c45fSAndroid Build Coastguard Worker // Publish the key event.
3836*38e8c45fSAndroid Build Coastguard Worker status = connection->inputPublisher
3837*38e8c45fSAndroid Build Coastguard Worker .publishKeyEvent(dispatchEntry->seq, keyEntry.id,
3838*38e8c45fSAndroid Build Coastguard Worker keyEntry.deviceId, keyEntry.source,
3839*38e8c45fSAndroid Build Coastguard Worker keyEntry.displayId, std::move(hmac),
3840*38e8c45fSAndroid Build Coastguard Worker keyEntry.action, dispatchEntry->resolvedFlags,
3841*38e8c45fSAndroid Build Coastguard Worker keyEntry.keyCode, keyEntry.scanCode,
3842*38e8c45fSAndroid Build Coastguard Worker keyEntry.metaState, keyEntry.repeatCount,
3843*38e8c45fSAndroid Build Coastguard Worker keyEntry.downTime, keyEntry.eventTime);
3844*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
3845*38e8c45fSAndroid Build Coastguard Worker ensureEventTraced(keyEntry);
3846*38e8c45fSAndroid Build Coastguard Worker mTracer->traceEventDispatch(*dispatchEntry, *keyEntry.traceTracker);
3847*38e8c45fSAndroid Build Coastguard Worker }
3848*38e8c45fSAndroid Build Coastguard Worker break;
3849*38e8c45fSAndroid Build Coastguard Worker }
3850*38e8c45fSAndroid Build Coastguard Worker
3851*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::MOTION: {
3852*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_OUTBOUND_EVENT_DETAILS) {
3853*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "Publishing " << *dispatchEntry << " to "
3854*38e8c45fSAndroid Build Coastguard Worker << connection->getInputChannelName();
3855*38e8c45fSAndroid Build Coastguard Worker }
3856*38e8c45fSAndroid Build Coastguard Worker const MotionEntry& motionEntry = static_cast<const MotionEntry&>(eventEntry);
3857*38e8c45fSAndroid Build Coastguard Worker status = publishMotionEvent(*connection, *dispatchEntry);
3858*38e8c45fSAndroid Build Coastguard Worker if (status == BAD_VALUE) {
3859*38e8c45fSAndroid Build Coastguard Worker logDispatchStateLocked();
3860*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << "Publisher failed for " << motionEntry;
3861*38e8c45fSAndroid Build Coastguard Worker }
3862*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
3863*38e8c45fSAndroid Build Coastguard Worker ensureEventTraced(motionEntry);
3864*38e8c45fSAndroid Build Coastguard Worker mTracer->traceEventDispatch(*dispatchEntry, *motionEntry.traceTracker);
3865*38e8c45fSAndroid Build Coastguard Worker }
3866*38e8c45fSAndroid Build Coastguard Worker break;
3867*38e8c45fSAndroid Build Coastguard Worker }
3868*38e8c45fSAndroid Build Coastguard Worker
3869*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::FOCUS: {
3870*38e8c45fSAndroid Build Coastguard Worker const FocusEntry& focusEntry = static_cast<const FocusEntry&>(eventEntry);
3871*38e8c45fSAndroid Build Coastguard Worker status = connection->inputPublisher.publishFocusEvent(dispatchEntry->seq,
3872*38e8c45fSAndroid Build Coastguard Worker focusEntry.id,
3873*38e8c45fSAndroid Build Coastguard Worker focusEntry.hasFocus);
3874*38e8c45fSAndroid Build Coastguard Worker break;
3875*38e8c45fSAndroid Build Coastguard Worker }
3876*38e8c45fSAndroid Build Coastguard Worker
3877*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::TOUCH_MODE_CHANGED: {
3878*38e8c45fSAndroid Build Coastguard Worker const TouchModeEntry& touchModeEntry =
3879*38e8c45fSAndroid Build Coastguard Worker static_cast<const TouchModeEntry&>(eventEntry);
3880*38e8c45fSAndroid Build Coastguard Worker status = connection->inputPublisher
3881*38e8c45fSAndroid Build Coastguard Worker .publishTouchModeEvent(dispatchEntry->seq, touchModeEntry.id,
3882*38e8c45fSAndroid Build Coastguard Worker touchModeEntry.inTouchMode);
3883*38e8c45fSAndroid Build Coastguard Worker
3884*38e8c45fSAndroid Build Coastguard Worker break;
3885*38e8c45fSAndroid Build Coastguard Worker }
3886*38e8c45fSAndroid Build Coastguard Worker
3887*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::POINTER_CAPTURE_CHANGED: {
3888*38e8c45fSAndroid Build Coastguard Worker const auto& captureEntry =
3889*38e8c45fSAndroid Build Coastguard Worker static_cast<const PointerCaptureChangedEntry&>(eventEntry);
3890*38e8c45fSAndroid Build Coastguard Worker status =
3891*38e8c45fSAndroid Build Coastguard Worker connection->inputPublisher
3892*38e8c45fSAndroid Build Coastguard Worker .publishCaptureEvent(dispatchEntry->seq, captureEntry.id,
3893*38e8c45fSAndroid Build Coastguard Worker captureEntry.pointerCaptureRequest.isEnable());
3894*38e8c45fSAndroid Build Coastguard Worker break;
3895*38e8c45fSAndroid Build Coastguard Worker }
3896*38e8c45fSAndroid Build Coastguard Worker
3897*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::DRAG: {
3898*38e8c45fSAndroid Build Coastguard Worker const DragEntry& dragEntry = static_cast<const DragEntry&>(eventEntry);
3899*38e8c45fSAndroid Build Coastguard Worker status = connection->inputPublisher.publishDragEvent(dispatchEntry->seq,
3900*38e8c45fSAndroid Build Coastguard Worker dragEntry.id, dragEntry.x,
3901*38e8c45fSAndroid Build Coastguard Worker dragEntry.y,
3902*38e8c45fSAndroid Build Coastguard Worker dragEntry.isExiting);
3903*38e8c45fSAndroid Build Coastguard Worker break;
3904*38e8c45fSAndroid Build Coastguard Worker }
3905*38e8c45fSAndroid Build Coastguard Worker
3906*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::DEVICE_RESET:
3907*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::SENSOR: {
3908*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("Should never start dispatch cycles for %s events",
3909*38e8c45fSAndroid Build Coastguard Worker ftl::enum_string(eventEntry.type).c_str());
3910*38e8c45fSAndroid Build Coastguard Worker return;
3911*38e8c45fSAndroid Build Coastguard Worker }
3912*38e8c45fSAndroid Build Coastguard Worker }
3913*38e8c45fSAndroid Build Coastguard Worker
3914*38e8c45fSAndroid Build Coastguard Worker // Check the result.
3915*38e8c45fSAndroid Build Coastguard Worker if (status) {
3916*38e8c45fSAndroid Build Coastguard Worker if (status == WOULD_BLOCK) {
3917*38e8c45fSAndroid Build Coastguard Worker if (connection->waitQueue.empty()) {
3918*38e8c45fSAndroid Build Coastguard Worker ALOGE("channel '%s' ~ Could not publish event because the pipe is full. "
3919*38e8c45fSAndroid Build Coastguard Worker "This is unexpected because the wait queue is empty, so the pipe "
3920*38e8c45fSAndroid Build Coastguard Worker "should be empty and we shouldn't have any problems writing an "
3921*38e8c45fSAndroid Build Coastguard Worker "event to it, status=%s(%d)",
3922*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str(), statusToString(status).c_str(),
3923*38e8c45fSAndroid Build Coastguard Worker status);
3924*38e8c45fSAndroid Build Coastguard Worker abortBrokenDispatchCycleLocked(currentTime, connection, /*notify=*/true);
3925*38e8c45fSAndroid Build Coastguard Worker } else {
3926*38e8c45fSAndroid Build Coastguard Worker // Pipe is full and we are waiting for the app to finish process some events
3927*38e8c45fSAndroid Build Coastguard Worker // before sending more events to it.
3928*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_DISPATCH_CYCLE) {
3929*38e8c45fSAndroid Build Coastguard Worker ALOGD("channel '%s' ~ Could not publish event because the pipe is full, "
3930*38e8c45fSAndroid Build Coastguard Worker "waiting for the application to catch up",
3931*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str());
3932*38e8c45fSAndroid Build Coastguard Worker }
3933*38e8c45fSAndroid Build Coastguard Worker }
3934*38e8c45fSAndroid Build Coastguard Worker } else {
3935*38e8c45fSAndroid Build Coastguard Worker ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, "
3936*38e8c45fSAndroid Build Coastguard Worker "status=%s(%d)",
3937*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str(), statusToString(status).c_str(),
3938*38e8c45fSAndroid Build Coastguard Worker status);
3939*38e8c45fSAndroid Build Coastguard Worker abortBrokenDispatchCycleLocked(currentTime, connection, /*notify=*/true);
3940*38e8c45fSAndroid Build Coastguard Worker }
3941*38e8c45fSAndroid Build Coastguard Worker return;
3942*38e8c45fSAndroid Build Coastguard Worker }
3943*38e8c45fSAndroid Build Coastguard Worker
3944*38e8c45fSAndroid Build Coastguard Worker // Re-enqueue the event on the wait queue.
3945*38e8c45fSAndroid Build Coastguard Worker const nsecs_t timeoutTime = dispatchEntry->timeoutTime;
3946*38e8c45fSAndroid Build Coastguard Worker connection->waitQueue.emplace_back(std::move(dispatchEntry));
3947*38e8c45fSAndroid Build Coastguard Worker connection->outboundQueue.erase(connection->outboundQueue.begin());
3948*38e8c45fSAndroid Build Coastguard Worker traceOutboundQueueLength(*connection);
3949*38e8c45fSAndroid Build Coastguard Worker if (connection->responsive) {
3950*38e8c45fSAndroid Build Coastguard Worker mAnrTracker.insert(timeoutTime, connection->getToken());
3951*38e8c45fSAndroid Build Coastguard Worker }
3952*38e8c45fSAndroid Build Coastguard Worker traceWaitQueueLength(*connection);
3953*38e8c45fSAndroid Build Coastguard Worker }
3954*38e8c45fSAndroid Build Coastguard Worker }
3955*38e8c45fSAndroid Build Coastguard Worker
sign(const VerifiedInputEvent & event) const3956*38e8c45fSAndroid Build Coastguard Worker std::array<uint8_t, 32> InputDispatcher::sign(const VerifiedInputEvent& event) const {
3957*38e8c45fSAndroid Build Coastguard Worker size_t size;
3958*38e8c45fSAndroid Build Coastguard Worker switch (event.type) {
3959*38e8c45fSAndroid Build Coastguard Worker case VerifiedInputEvent::Type::KEY: {
3960*38e8c45fSAndroid Build Coastguard Worker size = sizeof(VerifiedKeyEvent);
3961*38e8c45fSAndroid Build Coastguard Worker break;
3962*38e8c45fSAndroid Build Coastguard Worker }
3963*38e8c45fSAndroid Build Coastguard Worker case VerifiedInputEvent::Type::MOTION: {
3964*38e8c45fSAndroid Build Coastguard Worker size = sizeof(VerifiedMotionEvent);
3965*38e8c45fSAndroid Build Coastguard Worker break;
3966*38e8c45fSAndroid Build Coastguard Worker }
3967*38e8c45fSAndroid Build Coastguard Worker }
3968*38e8c45fSAndroid Build Coastguard Worker const uint8_t* start = reinterpret_cast<const uint8_t*>(&event);
3969*38e8c45fSAndroid Build Coastguard Worker return mHmacKeyManager.sign(start, size);
3970*38e8c45fSAndroid Build Coastguard Worker }
3971*38e8c45fSAndroid Build Coastguard Worker
getSignature(const MotionEntry & motionEntry,const DispatchEntry & dispatchEntry) const3972*38e8c45fSAndroid Build Coastguard Worker const std::array<uint8_t, 32> InputDispatcher::getSignature(
3973*38e8c45fSAndroid Build Coastguard Worker const MotionEntry& motionEntry, const DispatchEntry& dispatchEntry) const {
3974*38e8c45fSAndroid Build Coastguard Worker const int32_t actionMasked = MotionEvent::getActionMasked(motionEntry.action);
3975*38e8c45fSAndroid Build Coastguard Worker if (actionMasked != AMOTION_EVENT_ACTION_UP && actionMasked != AMOTION_EVENT_ACTION_DOWN) {
3976*38e8c45fSAndroid Build Coastguard Worker // Only sign events up and down events as the purely move events
3977*38e8c45fSAndroid Build Coastguard Worker // are tied to their up/down counterparts so signing would be redundant.
3978*38e8c45fSAndroid Build Coastguard Worker return INVALID_HMAC;
3979*38e8c45fSAndroid Build Coastguard Worker }
3980*38e8c45fSAndroid Build Coastguard Worker
3981*38e8c45fSAndroid Build Coastguard Worker VerifiedMotionEvent verifiedEvent =
3982*38e8c45fSAndroid Build Coastguard Worker verifiedMotionEventFromMotionEntry(motionEntry, dispatchEntry.rawTransform);
3983*38e8c45fSAndroid Build Coastguard Worker verifiedEvent.actionMasked = actionMasked;
3984*38e8c45fSAndroid Build Coastguard Worker verifiedEvent.flags = dispatchEntry.resolvedFlags & VERIFIED_MOTION_EVENT_FLAGS;
3985*38e8c45fSAndroid Build Coastguard Worker return sign(verifiedEvent);
3986*38e8c45fSAndroid Build Coastguard Worker }
3987*38e8c45fSAndroid Build Coastguard Worker
getSignature(const KeyEntry & keyEntry,const DispatchEntry & dispatchEntry) const3988*38e8c45fSAndroid Build Coastguard Worker const std::array<uint8_t, 32> InputDispatcher::getSignature(
3989*38e8c45fSAndroid Build Coastguard Worker const KeyEntry& keyEntry, const DispatchEntry& dispatchEntry) const {
3990*38e8c45fSAndroid Build Coastguard Worker VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEntry(keyEntry);
3991*38e8c45fSAndroid Build Coastguard Worker verifiedEvent.flags = dispatchEntry.resolvedFlags & VERIFIED_KEY_EVENT_FLAGS;
3992*38e8c45fSAndroid Build Coastguard Worker return sign(verifiedEvent);
3993*38e8c45fSAndroid Build Coastguard Worker }
3994*38e8c45fSAndroid Build Coastguard Worker
finishDispatchCycleLocked(nsecs_t currentTime,const std::shared_ptr<Connection> & connection,uint32_t seq,bool handled,nsecs_t consumeTime)3995*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
3996*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<Connection>& connection,
3997*38e8c45fSAndroid Build Coastguard Worker uint32_t seq, bool handled, nsecs_t consumeTime) {
3998*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_DISPATCH_CYCLE) {
3999*38e8c45fSAndroid Build Coastguard Worker ALOGD("channel '%s' ~ finishDispatchCycle - seq=%u, handled=%s",
4000*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str(), seq, toString(handled));
4001*38e8c45fSAndroid Build Coastguard Worker }
4002*38e8c45fSAndroid Build Coastguard Worker
4003*38e8c45fSAndroid Build Coastguard Worker if (connection->status != Connection::Status::NORMAL) {
4004*38e8c45fSAndroid Build Coastguard Worker return;
4005*38e8c45fSAndroid Build Coastguard Worker }
4006*38e8c45fSAndroid Build Coastguard Worker
4007*38e8c45fSAndroid Build Coastguard Worker // Notify other system components and prepare to start the next dispatch cycle.
4008*38e8c45fSAndroid Build Coastguard Worker auto command = [this, currentTime, connection, seq, handled, consumeTime]() REQUIRES(mLock) {
4009*38e8c45fSAndroid Build Coastguard Worker doDispatchCycleFinishedCommand(currentTime, connection, seq, handled, consumeTime);
4010*38e8c45fSAndroid Build Coastguard Worker };
4011*38e8c45fSAndroid Build Coastguard Worker postCommandLocked(std::move(command));
4012*38e8c45fSAndroid Build Coastguard Worker }
4013*38e8c45fSAndroid Build Coastguard Worker
abortBrokenDispatchCycleLocked(nsecs_t currentTime,const std::shared_ptr<Connection> & connection,bool notify)4014*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime,
4015*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<Connection>& connection,
4016*38e8c45fSAndroid Build Coastguard Worker bool notify) {
4017*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_DISPATCH_CYCLE) {
4018*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "channel '" << connection->getInputChannelName() << "'~ " << __func__
4019*38e8c45fSAndroid Build Coastguard Worker << " - notify=" << toString(notify);
4020*38e8c45fSAndroid Build Coastguard Worker }
4021*38e8c45fSAndroid Build Coastguard Worker
4022*38e8c45fSAndroid Build Coastguard Worker // Clear the dispatch queues.
4023*38e8c45fSAndroid Build Coastguard Worker drainDispatchQueue(connection->outboundQueue);
4024*38e8c45fSAndroid Build Coastguard Worker traceOutboundQueueLength(*connection);
4025*38e8c45fSAndroid Build Coastguard Worker drainDispatchQueue(connection->waitQueue);
4026*38e8c45fSAndroid Build Coastguard Worker traceWaitQueueLength(*connection);
4027*38e8c45fSAndroid Build Coastguard Worker
4028*38e8c45fSAndroid Build Coastguard Worker // The connection appears to be unrecoverably broken.
4029*38e8c45fSAndroid Build Coastguard Worker // Ignore already broken or zombie connections.
4030*38e8c45fSAndroid Build Coastguard Worker if (connection->status == Connection::Status::NORMAL) {
4031*38e8c45fSAndroid Build Coastguard Worker connection->status = Connection::Status::BROKEN;
4032*38e8c45fSAndroid Build Coastguard Worker
4033*38e8c45fSAndroid Build Coastguard Worker if (notify) {
4034*38e8c45fSAndroid Build Coastguard Worker // Notify other system components.
4035*38e8c45fSAndroid Build Coastguard Worker ALOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
4036*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str());
4037*38e8c45fSAndroid Build Coastguard Worker
4038*38e8c45fSAndroid Build Coastguard Worker auto command = [this, connection]() REQUIRES(mLock) {
4039*38e8c45fSAndroid Build Coastguard Worker scoped_unlock unlock(mLock);
4040*38e8c45fSAndroid Build Coastguard Worker mPolicy.notifyInputChannelBroken(connection->getToken());
4041*38e8c45fSAndroid Build Coastguard Worker };
4042*38e8c45fSAndroid Build Coastguard Worker postCommandLocked(std::move(command));
4043*38e8c45fSAndroid Build Coastguard Worker }
4044*38e8c45fSAndroid Build Coastguard Worker }
4045*38e8c45fSAndroid Build Coastguard Worker }
4046*38e8c45fSAndroid Build Coastguard Worker
drainDispatchQueue(std::deque<std::unique_ptr<DispatchEntry>> & queue)4047*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::drainDispatchQueue(std::deque<std::unique_ptr<DispatchEntry>>& queue) {
4048*38e8c45fSAndroid Build Coastguard Worker while (!queue.empty()) {
4049*38e8c45fSAndroid Build Coastguard Worker releaseDispatchEntry(std::move(queue.front()));
4050*38e8c45fSAndroid Build Coastguard Worker queue.pop_front();
4051*38e8c45fSAndroid Build Coastguard Worker }
4052*38e8c45fSAndroid Build Coastguard Worker }
4053*38e8c45fSAndroid Build Coastguard Worker
releaseDispatchEntry(std::unique_ptr<DispatchEntry> dispatchEntry)4054*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::releaseDispatchEntry(std::unique_ptr<DispatchEntry> dispatchEntry) {
4055*38e8c45fSAndroid Build Coastguard Worker if (dispatchEntry->hasForegroundTarget()) {
4056*38e8c45fSAndroid Build Coastguard Worker decrementPendingForegroundDispatches(*(dispatchEntry->eventEntry));
4057*38e8c45fSAndroid Build Coastguard Worker }
4058*38e8c45fSAndroid Build Coastguard Worker }
4059*38e8c45fSAndroid Build Coastguard Worker
handleReceiveCallback(int events,sp<IBinder> connectionToken)4060*38e8c45fSAndroid Build Coastguard Worker int InputDispatcher::handleReceiveCallback(int events, sp<IBinder> connectionToken) {
4061*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
4062*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<Connection> connection = getConnectionLocked(connectionToken);
4063*38e8c45fSAndroid Build Coastguard Worker if (connection == nullptr) {
4064*38e8c45fSAndroid Build Coastguard Worker ALOGW("Received looper callback for unknown input channel token %p. events=0x%x",
4065*38e8c45fSAndroid Build Coastguard Worker connectionToken.get(), events);
4066*38e8c45fSAndroid Build Coastguard Worker return 0; // remove the callback
4067*38e8c45fSAndroid Build Coastguard Worker }
4068*38e8c45fSAndroid Build Coastguard Worker
4069*38e8c45fSAndroid Build Coastguard Worker bool notify;
4070*38e8c45fSAndroid Build Coastguard Worker if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {
4071*38e8c45fSAndroid Build Coastguard Worker if (!(events & ALOOPER_EVENT_INPUT)) {
4072*38e8c45fSAndroid Build Coastguard Worker ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
4073*38e8c45fSAndroid Build Coastguard Worker "events=0x%x",
4074*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str(), events);
4075*38e8c45fSAndroid Build Coastguard Worker return 1;
4076*38e8c45fSAndroid Build Coastguard Worker }
4077*38e8c45fSAndroid Build Coastguard Worker
4078*38e8c45fSAndroid Build Coastguard Worker nsecs_t currentTime = now();
4079*38e8c45fSAndroid Build Coastguard Worker bool gotOne = false;
4080*38e8c45fSAndroid Build Coastguard Worker status_t status = OK;
4081*38e8c45fSAndroid Build Coastguard Worker for (;;) {
4082*38e8c45fSAndroid Build Coastguard Worker Result<InputPublisher::ConsumerResponse> result =
4083*38e8c45fSAndroid Build Coastguard Worker connection->inputPublisher.receiveConsumerResponse();
4084*38e8c45fSAndroid Build Coastguard Worker if (!result.ok()) {
4085*38e8c45fSAndroid Build Coastguard Worker status = result.error().code();
4086*38e8c45fSAndroid Build Coastguard Worker break;
4087*38e8c45fSAndroid Build Coastguard Worker }
4088*38e8c45fSAndroid Build Coastguard Worker
4089*38e8c45fSAndroid Build Coastguard Worker if (std::holds_alternative<InputPublisher::Finished>(*result)) {
4090*38e8c45fSAndroid Build Coastguard Worker const InputPublisher::Finished& finish =
4091*38e8c45fSAndroid Build Coastguard Worker std::get<InputPublisher::Finished>(*result);
4092*38e8c45fSAndroid Build Coastguard Worker finishDispatchCycleLocked(currentTime, connection, finish.seq, finish.handled,
4093*38e8c45fSAndroid Build Coastguard Worker finish.consumeTime);
4094*38e8c45fSAndroid Build Coastguard Worker } else if (std::holds_alternative<InputPublisher::Timeline>(*result)) {
4095*38e8c45fSAndroid Build Coastguard Worker if (shouldReportMetricsForConnection(*connection)) {
4096*38e8c45fSAndroid Build Coastguard Worker const InputPublisher::Timeline& timeline =
4097*38e8c45fSAndroid Build Coastguard Worker std::get<InputPublisher::Timeline>(*result);
4098*38e8c45fSAndroid Build Coastguard Worker mLatencyTracker.trackGraphicsLatency(timeline.inputEventId,
4099*38e8c45fSAndroid Build Coastguard Worker connection->getToken(),
4100*38e8c45fSAndroid Build Coastguard Worker std::move(timeline.graphicsTimeline));
4101*38e8c45fSAndroid Build Coastguard Worker }
4102*38e8c45fSAndroid Build Coastguard Worker }
4103*38e8c45fSAndroid Build Coastguard Worker gotOne = true;
4104*38e8c45fSAndroid Build Coastguard Worker }
4105*38e8c45fSAndroid Build Coastguard Worker if (gotOne) {
4106*38e8c45fSAndroid Build Coastguard Worker runCommandsLockedInterruptable();
4107*38e8c45fSAndroid Build Coastguard Worker if (status == WOULD_BLOCK) {
4108*38e8c45fSAndroid Build Coastguard Worker return 1;
4109*38e8c45fSAndroid Build Coastguard Worker }
4110*38e8c45fSAndroid Build Coastguard Worker }
4111*38e8c45fSAndroid Build Coastguard Worker
4112*38e8c45fSAndroid Build Coastguard Worker notify = status != DEAD_OBJECT || !connection->monitor;
4113*38e8c45fSAndroid Build Coastguard Worker if (notify) {
4114*38e8c45fSAndroid Build Coastguard Worker ALOGE("channel '%s' ~ Failed to receive finished signal. status=%s(%d)",
4115*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str(), statusToString(status).c_str(),
4116*38e8c45fSAndroid Build Coastguard Worker status);
4117*38e8c45fSAndroid Build Coastguard Worker }
4118*38e8c45fSAndroid Build Coastguard Worker } else {
4119*38e8c45fSAndroid Build Coastguard Worker // Monitor channels are never explicitly unregistered.
4120*38e8c45fSAndroid Build Coastguard Worker // We do it automatically when the remote endpoint is closed so don't warn about them.
4121*38e8c45fSAndroid Build Coastguard Worker const bool stillHaveWindowHandle = getWindowHandleLocked(connection->getToken()) != nullptr;
4122*38e8c45fSAndroid Build Coastguard Worker notify = !connection->monitor && stillHaveWindowHandle;
4123*38e8c45fSAndroid Build Coastguard Worker if (notify) {
4124*38e8c45fSAndroid Build Coastguard Worker ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred. events=0x%x",
4125*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str(), events);
4126*38e8c45fSAndroid Build Coastguard Worker }
4127*38e8c45fSAndroid Build Coastguard Worker }
4128*38e8c45fSAndroid Build Coastguard Worker
4129*38e8c45fSAndroid Build Coastguard Worker // Remove the channel.
4130*38e8c45fSAndroid Build Coastguard Worker removeInputChannelLocked(connection->getToken(), notify);
4131*38e8c45fSAndroid Build Coastguard Worker return 0; // remove the callback
4132*38e8c45fSAndroid Build Coastguard Worker }
4133*38e8c45fSAndroid Build Coastguard Worker
synthesizeCancelationEventsForAllConnectionsLocked(const CancelationOptions & options)4134*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked(
4135*38e8c45fSAndroid Build Coastguard Worker const CancelationOptions& options) {
4136*38e8c45fSAndroid Build Coastguard Worker // Cancel windows (i.e. non-monitors).
4137*38e8c45fSAndroid Build Coastguard Worker // A channel must have at least one window to receive any input. If a window was removed, the
4138*38e8c45fSAndroid Build Coastguard Worker // event streams directed to the window will already have been canceled during window removal.
4139*38e8c45fSAndroid Build Coastguard Worker // So there is no need to generate cancellations for connections without any windows.
4140*38e8c45fSAndroid Build Coastguard Worker const auto [cancelPointers, cancelNonPointers] = expandCancellationMode(options.mode);
4141*38e8c45fSAndroid Build Coastguard Worker // Generate cancellations for touched windows first. This is to avoid generating cancellations
4142*38e8c45fSAndroid Build Coastguard Worker // through a non-touched window if there are more than one window for an input channel.
4143*38e8c45fSAndroid Build Coastguard Worker if (cancelPointers) {
4144*38e8c45fSAndroid Build Coastguard Worker for (const auto& [displayId, touchState] : mTouchStatesByDisplay) {
4145*38e8c45fSAndroid Build Coastguard Worker if (options.displayId.has_value() && options.displayId != displayId) {
4146*38e8c45fSAndroid Build Coastguard Worker continue;
4147*38e8c45fSAndroid Build Coastguard Worker }
4148*38e8c45fSAndroid Build Coastguard Worker for (const auto& touchedWindow : touchState.windows) {
4149*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForWindowLocked(touchedWindow.windowHandle, options);
4150*38e8c45fSAndroid Build Coastguard Worker }
4151*38e8c45fSAndroid Build Coastguard Worker }
4152*38e8c45fSAndroid Build Coastguard Worker }
4153*38e8c45fSAndroid Build Coastguard Worker // Follow up by generating cancellations for all windows, because we don't explicitly track
4154*38e8c45fSAndroid Build Coastguard Worker // the windows that have an ongoing focus event stream.
4155*38e8c45fSAndroid Build Coastguard Worker if (cancelNonPointers) {
4156*38e8c45fSAndroid Build Coastguard Worker for (const auto& [_, handles] : mWindowHandlesByDisplay) {
4157*38e8c45fSAndroid Build Coastguard Worker for (const auto& windowHandle : handles) {
4158*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForWindowLocked(windowHandle, options);
4159*38e8c45fSAndroid Build Coastguard Worker }
4160*38e8c45fSAndroid Build Coastguard Worker }
4161*38e8c45fSAndroid Build Coastguard Worker }
4162*38e8c45fSAndroid Build Coastguard Worker
4163*38e8c45fSAndroid Build Coastguard Worker // Cancel monitors.
4164*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForMonitorsLocked(options);
4165*38e8c45fSAndroid Build Coastguard Worker }
4166*38e8c45fSAndroid Build Coastguard Worker
synthesizeCancelationEventsForMonitorsLocked(const CancelationOptions & options)4167*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked(
4168*38e8c45fSAndroid Build Coastguard Worker const CancelationOptions& options) {
4169*38e8c45fSAndroid Build Coastguard Worker for (const auto& [_, monitors] : mGlobalMonitorsByDisplay) {
4170*38e8c45fSAndroid Build Coastguard Worker for (const Monitor& monitor : monitors) {
4171*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForConnectionLocked(monitor.connection, options,
4172*38e8c45fSAndroid Build Coastguard Worker /*window=*/nullptr);
4173*38e8c45fSAndroid Build Coastguard Worker }
4174*38e8c45fSAndroid Build Coastguard Worker }
4175*38e8c45fSAndroid Build Coastguard Worker }
4176*38e8c45fSAndroid Build Coastguard Worker
synthesizeCancelationEventsForWindowLocked(const sp<WindowInfoHandle> & windowHandle,const CancelationOptions & options,const std::shared_ptr<Connection> & connection)4177*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::synthesizeCancelationEventsForWindowLocked(
4178*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle>& windowHandle, const CancelationOptions& options,
4179*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<Connection>& connection) {
4180*38e8c45fSAndroid Build Coastguard Worker if (windowHandle == nullptr) {
4181*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << __func__ << ": Window handle must not be null";
4182*38e8c45fSAndroid Build Coastguard Worker }
4183*38e8c45fSAndroid Build Coastguard Worker if (connection) {
4184*38e8c45fSAndroid Build Coastguard Worker // The connection can be optionally provided to avoid multiple lookups.
4185*38e8c45fSAndroid Build Coastguard Worker if (windowHandle->getToken() != connection->getToken()) {
4186*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << __func__
4187*38e8c45fSAndroid Build Coastguard Worker << ": Wrong connection provided for window: " << windowHandle->getName();
4188*38e8c45fSAndroid Build Coastguard Worker }
4189*38e8c45fSAndroid Build Coastguard Worker }
4190*38e8c45fSAndroid Build Coastguard Worker
4191*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<Connection> resolvedConnection =
4192*38e8c45fSAndroid Build Coastguard Worker connection ? connection : getConnectionLocked(windowHandle->getToken());
4193*38e8c45fSAndroid Build Coastguard Worker if (!resolvedConnection) {
4194*38e8c45fSAndroid Build Coastguard Worker LOG(DEBUG) << __func__ << "No connection found for window: " << windowHandle->getName();
4195*38e8c45fSAndroid Build Coastguard Worker return;
4196*38e8c45fSAndroid Build Coastguard Worker }
4197*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForConnectionLocked(resolvedConnection, options, windowHandle);
4198*38e8c45fSAndroid Build Coastguard Worker }
4199*38e8c45fSAndroid Build Coastguard Worker
synthesizeCancelationEventsForConnectionLocked(const std::shared_ptr<Connection> & connection,const CancelationOptions & options,const sp<WindowInfoHandle> & window)4200*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
4201*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<Connection>& connection, const CancelationOptions& options,
4202*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle>& window) {
4203*38e8c45fSAndroid Build Coastguard Worker if (!connection->monitor && window == nullptr) {
4204*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << __func__
4205*38e8c45fSAndroid Build Coastguard Worker << ": Cannot send event to non-monitor channel without a window - channel: "
4206*38e8c45fSAndroid Build Coastguard Worker << connection->getInputChannelName();
4207*38e8c45fSAndroid Build Coastguard Worker }
4208*38e8c45fSAndroid Build Coastguard Worker if (connection->status != Connection::Status::NORMAL) {
4209*38e8c45fSAndroid Build Coastguard Worker return;
4210*38e8c45fSAndroid Build Coastguard Worker }
4211*38e8c45fSAndroid Build Coastguard Worker
4212*38e8c45fSAndroid Build Coastguard Worker nsecs_t currentTime = now();
4213*38e8c45fSAndroid Build Coastguard Worker
4214*38e8c45fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<EventEntry>> cancelationEvents =
4215*38e8c45fSAndroid Build Coastguard Worker connection->inputState.synthesizeCancelationEvents(currentTime, options);
4216*38e8c45fSAndroid Build Coastguard Worker
4217*38e8c45fSAndroid Build Coastguard Worker if (cancelationEvents.empty()) {
4218*38e8c45fSAndroid Build Coastguard Worker return;
4219*38e8c45fSAndroid Build Coastguard Worker }
4220*38e8c45fSAndroid Build Coastguard Worker
4221*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_OUTBOUND_EVENT_DETAILS) {
4222*38e8c45fSAndroid Build Coastguard Worker ALOGD("channel '%s' ~ Synthesized %zu cancelation events to bring channel back in sync "
4223*38e8c45fSAndroid Build Coastguard Worker "with reality: %s, mode=%s.",
4224*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str(), cancelationEvents.size(), options.reason,
4225*38e8c45fSAndroid Build Coastguard Worker ftl::enum_string(options.mode).c_str());
4226*38e8c45fSAndroid Build Coastguard Worker }
4227*38e8c45fSAndroid Build Coastguard Worker
4228*38e8c45fSAndroid Build Coastguard Worker std::string reason = std::string("reason=").append(options.reason);
4229*38e8c45fSAndroid Build Coastguard Worker android_log_event_list(LOGTAG_INPUT_CANCEL)
4230*38e8c45fSAndroid Build Coastguard Worker << connection->getInputChannelName().c_str() << reason << LOG_ID_EVENTS;
4231*38e8c45fSAndroid Build Coastguard Worker
4232*38e8c45fSAndroid Build Coastguard Worker const bool wasEmpty = connection->outboundQueue.empty();
4233*38e8c45fSAndroid Build Coastguard Worker // The target to use if we don't find a window associated with the channel.
4234*38e8c45fSAndroid Build Coastguard Worker const InputTarget fallbackTarget{connection};
4235*38e8c45fSAndroid Build Coastguard Worker const auto& token = connection->getToken();
4236*38e8c45fSAndroid Build Coastguard Worker
4237*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < cancelationEvents.size(); i++) {
4238*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<EventEntry> cancelationEventEntry = std::move(cancelationEvents[i]);
4239*38e8c45fSAndroid Build Coastguard Worker std::vector<InputTarget> targets{};
4240*38e8c45fSAndroid Build Coastguard Worker
4241*38e8c45fSAndroid Build Coastguard Worker switch (cancelationEventEntry->type) {
4242*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::KEY: {
4243*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
4244*38e8c45fSAndroid Build Coastguard Worker static_cast<KeyEntry&>(*cancelationEventEntry).traceTracker =
4245*38e8c45fSAndroid Build Coastguard Worker mTracer->traceDerivedEvent(*cancelationEventEntry,
4246*38e8c45fSAndroid Build Coastguard Worker *options.traceTracker);
4247*38e8c45fSAndroid Build Coastguard Worker }
4248*38e8c45fSAndroid Build Coastguard Worker const auto& keyEntry = static_cast<const KeyEntry&>(*cancelationEventEntry);
4249*38e8c45fSAndroid Build Coastguard Worker if (window) {
4250*38e8c45fSAndroid Build Coastguard Worker addWindowTargetLocked(window, InputTarget::DispatchMode::AS_IS,
4251*38e8c45fSAndroid Build Coastguard Worker /*targetFlags=*/{}, keyEntry.downTime, targets);
4252*38e8c45fSAndroid Build Coastguard Worker } else {
4253*38e8c45fSAndroid Build Coastguard Worker targets.emplace_back(fallbackTarget);
4254*38e8c45fSAndroid Build Coastguard Worker }
4255*38e8c45fSAndroid Build Coastguard Worker logOutboundKeyDetails("cancel - ", keyEntry);
4256*38e8c45fSAndroid Build Coastguard Worker break;
4257*38e8c45fSAndroid Build Coastguard Worker }
4258*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::MOTION: {
4259*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
4260*38e8c45fSAndroid Build Coastguard Worker static_cast<MotionEntry&>(*cancelationEventEntry).traceTracker =
4261*38e8c45fSAndroid Build Coastguard Worker mTracer->traceDerivedEvent(*cancelationEventEntry,
4262*38e8c45fSAndroid Build Coastguard Worker *options.traceTracker);
4263*38e8c45fSAndroid Build Coastguard Worker }
4264*38e8c45fSAndroid Build Coastguard Worker const auto& motionEntry = static_cast<const MotionEntry&>(*cancelationEventEntry);
4265*38e8c45fSAndroid Build Coastguard Worker if (window) {
4266*38e8c45fSAndroid Build Coastguard Worker std::bitset<MAX_POINTER_ID + 1> pointerIds;
4267*38e8c45fSAndroid Build Coastguard Worker for (uint32_t pointerIndex = 0; pointerIndex < motionEntry.getPointerCount();
4268*38e8c45fSAndroid Build Coastguard Worker pointerIndex++) {
4269*38e8c45fSAndroid Build Coastguard Worker pointerIds.set(motionEntry.pointerProperties[pointerIndex].id);
4270*38e8c45fSAndroid Build Coastguard Worker }
4271*38e8c45fSAndroid Build Coastguard Worker if (mDragState && mDragState->dragWindow->getToken() == token &&
4272*38e8c45fSAndroid Build Coastguard Worker pointerIds.test(mDragState->pointerId)) {
4273*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << __func__
4274*38e8c45fSAndroid Build Coastguard Worker << ": Canceling drag and drop because the pointers for the drag "
4275*38e8c45fSAndroid Build Coastguard Worker "window are being canceled.";
4276*38e8c45fSAndroid Build Coastguard Worker sendDropWindowCommandLocked(nullptr, /*x=*/0, /*y=*/0);
4277*38e8c45fSAndroid Build Coastguard Worker mDragState.reset();
4278*38e8c45fSAndroid Build Coastguard Worker }
4279*38e8c45fSAndroid Build Coastguard Worker addPointerWindowTargetLocked(window, InputTarget::DispatchMode::AS_IS,
4280*38e8c45fSAndroid Build Coastguard Worker ftl::Flags<InputTarget::Flags>(), pointerIds,
4281*38e8c45fSAndroid Build Coastguard Worker motionEntry.downTime, targets);
4282*38e8c45fSAndroid Build Coastguard Worker } else {
4283*38e8c45fSAndroid Build Coastguard Worker targets.emplace_back(fallbackTarget);
4284*38e8c45fSAndroid Build Coastguard Worker const auto it = mDisplayInfos.find(motionEntry.displayId);
4285*38e8c45fSAndroid Build Coastguard Worker if (it != mDisplayInfos.end()) {
4286*38e8c45fSAndroid Build Coastguard Worker targets.back().displayTransform = it->second.transform;
4287*38e8c45fSAndroid Build Coastguard Worker targets.back().setDefaultPointerTransform(it->second.transform);
4288*38e8c45fSAndroid Build Coastguard Worker }
4289*38e8c45fSAndroid Build Coastguard Worker }
4290*38e8c45fSAndroid Build Coastguard Worker logOutboundMotionDetails("cancel - ", motionEntry);
4291*38e8c45fSAndroid Build Coastguard Worker break;
4292*38e8c45fSAndroid Build Coastguard Worker }
4293*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::FOCUS:
4294*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::TOUCH_MODE_CHANGED:
4295*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::POINTER_CAPTURE_CHANGED:
4296*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::DRAG: {
4297*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("Canceling %s events is not supported",
4298*38e8c45fSAndroid Build Coastguard Worker ftl::enum_string(cancelationEventEntry->type).c_str());
4299*38e8c45fSAndroid Build Coastguard Worker break;
4300*38e8c45fSAndroid Build Coastguard Worker }
4301*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::DEVICE_RESET:
4302*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::SENSOR: {
4303*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("%s event should not be found inside Connections's queue",
4304*38e8c45fSAndroid Build Coastguard Worker ftl::enum_string(cancelationEventEntry->type).c_str());
4305*38e8c45fSAndroid Build Coastguard Worker break;
4306*38e8c45fSAndroid Build Coastguard Worker }
4307*38e8c45fSAndroid Build Coastguard Worker }
4308*38e8c45fSAndroid Build Coastguard Worker
4309*38e8c45fSAndroid Build Coastguard Worker if (targets.size() != 1) LOG(FATAL) << __func__ << ": InputTarget not created";
4310*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
4311*38e8c45fSAndroid Build Coastguard Worker mTracer->dispatchToTargetHint(*options.traceTracker, targets[0]);
4312*38e8c45fSAndroid Build Coastguard Worker }
4313*38e8c45fSAndroid Build Coastguard Worker enqueueDispatchEntryLocked(connection, std::move(cancelationEventEntry), targets[0]);
4314*38e8c45fSAndroid Build Coastguard Worker }
4315*38e8c45fSAndroid Build Coastguard Worker
4316*38e8c45fSAndroid Build Coastguard Worker // If the outbound queue was previously empty, start the dispatch cycle going.
4317*38e8c45fSAndroid Build Coastguard Worker if (wasEmpty && !connection->outboundQueue.empty()) {
4318*38e8c45fSAndroid Build Coastguard Worker startDispatchCycleLocked(currentTime, connection);
4319*38e8c45fSAndroid Build Coastguard Worker }
4320*38e8c45fSAndroid Build Coastguard Worker }
4321*38e8c45fSAndroid Build Coastguard Worker
synthesizePointerDownEventsForConnectionLocked(const nsecs_t downTime,const std::shared_ptr<Connection> & connection,ftl::Flags<InputTarget::Flags> targetFlags,const std::unique_ptr<trace::EventTrackerInterface> & traceTracker)4322*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::synthesizePointerDownEventsForConnectionLocked(
4323*38e8c45fSAndroid Build Coastguard Worker const nsecs_t downTime, const std::shared_ptr<Connection>& connection,
4324*38e8c45fSAndroid Build Coastguard Worker ftl::Flags<InputTarget::Flags> targetFlags,
4325*38e8c45fSAndroid Build Coastguard Worker const std::unique_ptr<trace::EventTrackerInterface>& traceTracker) {
4326*38e8c45fSAndroid Build Coastguard Worker if (connection->status != Connection::Status::NORMAL) {
4327*38e8c45fSAndroid Build Coastguard Worker return;
4328*38e8c45fSAndroid Build Coastguard Worker }
4329*38e8c45fSAndroid Build Coastguard Worker
4330*38e8c45fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<EventEntry>> downEvents =
4331*38e8c45fSAndroid Build Coastguard Worker connection->inputState.synthesizePointerDownEvents(downTime);
4332*38e8c45fSAndroid Build Coastguard Worker
4333*38e8c45fSAndroid Build Coastguard Worker if (downEvents.empty()) {
4334*38e8c45fSAndroid Build Coastguard Worker return;
4335*38e8c45fSAndroid Build Coastguard Worker }
4336*38e8c45fSAndroid Build Coastguard Worker
4337*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_OUTBOUND_EVENT_DETAILS) {
4338*38e8c45fSAndroid Build Coastguard Worker ALOGD("channel '%s' ~ Synthesized %zu down events to ensure consistent event stream.",
4339*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str(), downEvents.size());
4340*38e8c45fSAndroid Build Coastguard Worker }
4341*38e8c45fSAndroid Build Coastguard Worker
4342*38e8c45fSAndroid Build Coastguard Worker const auto [_, touchedWindowState, displayId] =
4343*38e8c45fSAndroid Build Coastguard Worker findTouchStateWindowAndDisplayLocked(connection->getToken());
4344*38e8c45fSAndroid Build Coastguard Worker if (touchedWindowState == nullptr) {
4345*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << __func__ << ": Touch state is out of sync: No touched window for token";
4346*38e8c45fSAndroid Build Coastguard Worker }
4347*38e8c45fSAndroid Build Coastguard Worker const auto& windowHandle = touchedWindowState->windowHandle;
4348*38e8c45fSAndroid Build Coastguard Worker
4349*38e8c45fSAndroid Build Coastguard Worker const bool wasEmpty = connection->outboundQueue.empty();
4350*38e8c45fSAndroid Build Coastguard Worker for (std::unique_ptr<EventEntry>& downEventEntry : downEvents) {
4351*38e8c45fSAndroid Build Coastguard Worker std::vector<InputTarget> targets{};
4352*38e8c45fSAndroid Build Coastguard Worker switch (downEventEntry->type) {
4353*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::MOTION: {
4354*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
4355*38e8c45fSAndroid Build Coastguard Worker static_cast<MotionEntry&>(*downEventEntry).traceTracker =
4356*38e8c45fSAndroid Build Coastguard Worker mTracer->traceDerivedEvent(*downEventEntry, *traceTracker);
4357*38e8c45fSAndroid Build Coastguard Worker }
4358*38e8c45fSAndroid Build Coastguard Worker const auto& motionEntry = static_cast<const MotionEntry&>(*downEventEntry);
4359*38e8c45fSAndroid Build Coastguard Worker if (windowHandle != nullptr) {
4360*38e8c45fSAndroid Build Coastguard Worker std::bitset<MAX_POINTER_ID + 1> pointerIds;
4361*38e8c45fSAndroid Build Coastguard Worker for (uint32_t pointerIndex = 0; pointerIndex < motionEntry.getPointerCount();
4362*38e8c45fSAndroid Build Coastguard Worker pointerIndex++) {
4363*38e8c45fSAndroid Build Coastguard Worker pointerIds.set(motionEntry.pointerProperties[pointerIndex].id);
4364*38e8c45fSAndroid Build Coastguard Worker }
4365*38e8c45fSAndroid Build Coastguard Worker addPointerWindowTargetLocked(windowHandle, InputTarget::DispatchMode::AS_IS,
4366*38e8c45fSAndroid Build Coastguard Worker targetFlags, pointerIds, motionEntry.downTime,
4367*38e8c45fSAndroid Build Coastguard Worker targets);
4368*38e8c45fSAndroid Build Coastguard Worker } else {
4369*38e8c45fSAndroid Build Coastguard Worker targets.emplace_back(connection, targetFlags);
4370*38e8c45fSAndroid Build Coastguard Worker const auto it = mDisplayInfos.find(motionEntry.displayId);
4371*38e8c45fSAndroid Build Coastguard Worker if (it != mDisplayInfos.end()) {
4372*38e8c45fSAndroid Build Coastguard Worker targets.back().displayTransform = it->second.transform;
4373*38e8c45fSAndroid Build Coastguard Worker targets.back().setDefaultPointerTransform(it->second.transform);
4374*38e8c45fSAndroid Build Coastguard Worker }
4375*38e8c45fSAndroid Build Coastguard Worker }
4376*38e8c45fSAndroid Build Coastguard Worker logOutboundMotionDetails("down - ", motionEntry);
4377*38e8c45fSAndroid Build Coastguard Worker break;
4378*38e8c45fSAndroid Build Coastguard Worker }
4379*38e8c45fSAndroid Build Coastguard Worker
4380*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::KEY:
4381*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::FOCUS:
4382*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::TOUCH_MODE_CHANGED:
4383*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::DEVICE_RESET:
4384*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::POINTER_CAPTURE_CHANGED:
4385*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::SENSOR:
4386*38e8c45fSAndroid Build Coastguard Worker case EventEntry::Type::DRAG: {
4387*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("%s event should not be found inside Connections's queue",
4388*38e8c45fSAndroid Build Coastguard Worker ftl::enum_string(downEventEntry->type).c_str());
4389*38e8c45fSAndroid Build Coastguard Worker break;
4390*38e8c45fSAndroid Build Coastguard Worker }
4391*38e8c45fSAndroid Build Coastguard Worker }
4392*38e8c45fSAndroid Build Coastguard Worker
4393*38e8c45fSAndroid Build Coastguard Worker if (targets.size() != 1) LOG(FATAL) << __func__ << ": InputTarget not created";
4394*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
4395*38e8c45fSAndroid Build Coastguard Worker mTracer->dispatchToTargetHint(*traceTracker, targets[0]);
4396*38e8c45fSAndroid Build Coastguard Worker }
4397*38e8c45fSAndroid Build Coastguard Worker enqueueDispatchEntryLocked(connection, std::move(downEventEntry), targets[0]);
4398*38e8c45fSAndroid Build Coastguard Worker }
4399*38e8c45fSAndroid Build Coastguard Worker
4400*38e8c45fSAndroid Build Coastguard Worker // If the outbound queue was previously empty, start the dispatch cycle going.
4401*38e8c45fSAndroid Build Coastguard Worker if (wasEmpty && !connection->outboundQueue.empty()) {
4402*38e8c45fSAndroid Build Coastguard Worker startDispatchCycleLocked(downTime, connection);
4403*38e8c45fSAndroid Build Coastguard Worker }
4404*38e8c45fSAndroid Build Coastguard Worker }
4405*38e8c45fSAndroid Build Coastguard Worker
splitMotionEvent(const MotionEntry & originalMotionEntry,std::bitset<MAX_POINTER_ID+1> pointerIds,nsecs_t splitDownTime)4406*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<MotionEntry> InputDispatcher::splitMotionEvent(
4407*38e8c45fSAndroid Build Coastguard Worker const MotionEntry& originalMotionEntry, std::bitset<MAX_POINTER_ID + 1> pointerIds,
4408*38e8c45fSAndroid Build Coastguard Worker nsecs_t splitDownTime) {
4409*38e8c45fSAndroid Build Coastguard Worker const auto& [action, pointerProperties, pointerCoords] =
4410*38e8c45fSAndroid Build Coastguard Worker MotionEvent::split(originalMotionEntry.action, originalMotionEntry.flags,
4411*38e8c45fSAndroid Build Coastguard Worker /*historySize=*/0, originalMotionEntry.pointerProperties,
4412*38e8c45fSAndroid Build Coastguard Worker originalMotionEntry.pointerCoords, pointerIds);
4413*38e8c45fSAndroid Build Coastguard Worker if (pointerIds.count() != pointerCoords.size()) {
4414*38e8c45fSAndroid Build Coastguard Worker // TODO(b/329107108): Determine why some IDs in pointerIds were not in originalMotionEntry.
4415*38e8c45fSAndroid Build Coastguard Worker // This is bad. We are missing some of the pointers that we expected to deliver.
4416*38e8c45fSAndroid Build Coastguard Worker // Most likely this indicates that we received an ACTION_MOVE events that has
4417*38e8c45fSAndroid Build Coastguard Worker // different pointer ids than we expected based on the previous ACTION_DOWN
4418*38e8c45fSAndroid Build Coastguard Worker // or ACTION_POINTER_DOWN events that caused us to decide to split the pointers
4419*38e8c45fSAndroid Build Coastguard Worker // in this way.
4420*38e8c45fSAndroid Build Coastguard Worker ALOGW("Dropping split motion event because the pointer count is %zu but "
4421*38e8c45fSAndroid Build Coastguard Worker "we expected there to be %zu pointers. This probably means we received "
4422*38e8c45fSAndroid Build Coastguard Worker "a broken sequence of pointer ids from the input device: %s",
4423*38e8c45fSAndroid Build Coastguard Worker pointerCoords.size(), pointerIds.count(),
4424*38e8c45fSAndroid Build Coastguard Worker originalMotionEntry.getDescription().c_str());
4425*38e8c45fSAndroid Build Coastguard Worker return nullptr;
4426*38e8c45fSAndroid Build Coastguard Worker }
4427*38e8c45fSAndroid Build Coastguard Worker
4428*38e8c45fSAndroid Build Coastguard Worker // TODO(b/327503168): Move this check inside MotionEvent::split once all callers handle it
4429*38e8c45fSAndroid Build Coastguard Worker // correctly.
4430*38e8c45fSAndroid Build Coastguard Worker if (action == AMOTION_EVENT_ACTION_DOWN && splitDownTime != originalMotionEntry.eventTime) {
4431*38e8c45fSAndroid Build Coastguard Worker logDispatchStateLocked();
4432*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("Split motion event has mismatching downTime and eventTime for "
4433*38e8c45fSAndroid Build Coastguard Worker "ACTION_DOWN, motionEntry=%s, splitDownTime=%" PRId64,
4434*38e8c45fSAndroid Build Coastguard Worker originalMotionEntry.getDescription().c_str(), splitDownTime);
4435*38e8c45fSAndroid Build Coastguard Worker }
4436*38e8c45fSAndroid Build Coastguard Worker
4437*38e8c45fSAndroid Build Coastguard Worker int32_t newId = mIdGenerator.nextId();
4438*38e8c45fSAndroid Build Coastguard Worker ATRACE_NAME_IF(ATRACE_ENABLED(),
4439*38e8c45fSAndroid Build Coastguard Worker StringPrintf("Split MotionEvent(id=0x%" PRIx32 ") to MotionEvent(id=0x%" PRIx32
4440*38e8c45fSAndroid Build Coastguard Worker ").",
4441*38e8c45fSAndroid Build Coastguard Worker originalMotionEntry.id, newId));
4442*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<MotionEntry> splitMotionEntry =
4443*38e8c45fSAndroid Build Coastguard Worker std::make_unique<MotionEntry>(newId, originalMotionEntry.injectionState,
4444*38e8c45fSAndroid Build Coastguard Worker originalMotionEntry.eventTime,
4445*38e8c45fSAndroid Build Coastguard Worker originalMotionEntry.deviceId, originalMotionEntry.source,
4446*38e8c45fSAndroid Build Coastguard Worker originalMotionEntry.displayId,
4447*38e8c45fSAndroid Build Coastguard Worker originalMotionEntry.policyFlags, action,
4448*38e8c45fSAndroid Build Coastguard Worker originalMotionEntry.actionButton,
4449*38e8c45fSAndroid Build Coastguard Worker originalMotionEntry.flags, originalMotionEntry.metaState,
4450*38e8c45fSAndroid Build Coastguard Worker originalMotionEntry.buttonState,
4451*38e8c45fSAndroid Build Coastguard Worker originalMotionEntry.classification,
4452*38e8c45fSAndroid Build Coastguard Worker originalMotionEntry.edgeFlags,
4453*38e8c45fSAndroid Build Coastguard Worker originalMotionEntry.xPrecision,
4454*38e8c45fSAndroid Build Coastguard Worker originalMotionEntry.yPrecision,
4455*38e8c45fSAndroid Build Coastguard Worker originalMotionEntry.xCursorPosition,
4456*38e8c45fSAndroid Build Coastguard Worker originalMotionEntry.yCursorPosition, splitDownTime,
4457*38e8c45fSAndroid Build Coastguard Worker pointerProperties, pointerCoords);
4458*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
4459*38e8c45fSAndroid Build Coastguard Worker splitMotionEntry->traceTracker =
4460*38e8c45fSAndroid Build Coastguard Worker mTracer->traceDerivedEvent(*splitMotionEntry, *originalMotionEntry.traceTracker);
4461*38e8c45fSAndroid Build Coastguard Worker }
4462*38e8c45fSAndroid Build Coastguard Worker
4463*38e8c45fSAndroid Build Coastguard Worker return splitMotionEntry;
4464*38e8c45fSAndroid Build Coastguard Worker }
4465*38e8c45fSAndroid Build Coastguard Worker
notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs & args)4466*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
4467*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
4468*38e8c45fSAndroid Build Coastguard Worker // Reset key repeating in case a keyboard device was added or removed or something.
4469*38e8c45fSAndroid Build Coastguard Worker resetKeyRepeatLocked();
4470*38e8c45fSAndroid Build Coastguard Worker mLatencyTracker.setInputDevices(args.inputDeviceInfos);
4471*38e8c45fSAndroid Build Coastguard Worker }
4472*38e8c45fSAndroid Build Coastguard Worker
notifyKey(const NotifyKeyArgs & args)4473*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::notifyKey(const NotifyKeyArgs& args) {
4474*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(debugInboundEventDetails(),
4475*38e8c45fSAndroid Build Coastguard Worker "notifyKey - id=%" PRIx32 ", eventTime=%" PRId64
4476*38e8c45fSAndroid Build Coastguard Worker ", deviceId=%d, source=%s, displayId=%s, policyFlags=0x%x, action=%s, flags=0x%x, "
4477*38e8c45fSAndroid Build Coastguard Worker "keyCode=%s, scanCode=0x%x, metaState=0x%x, "
4478*38e8c45fSAndroid Build Coastguard Worker "downTime=%" PRId64,
4479*38e8c45fSAndroid Build Coastguard Worker args.id, args.eventTime, args.deviceId, inputEventSourceToString(args.source).c_str(),
4480*38e8c45fSAndroid Build Coastguard Worker args.displayId.toString().c_str(), args.policyFlags,
4481*38e8c45fSAndroid Build Coastguard Worker KeyEvent::actionToString(args.action), args.flags, KeyEvent::getLabel(args.keyCode),
4482*38e8c45fSAndroid Build Coastguard Worker args.scanCode, args.metaState, args.downTime);
4483*38e8c45fSAndroid Build Coastguard Worker Result<void> keyCheck = validateKeyEvent(args.action);
4484*38e8c45fSAndroid Build Coastguard Worker if (!keyCheck.ok()) {
4485*38e8c45fSAndroid Build Coastguard Worker LOG(ERROR) << "invalid key event: " << keyCheck.error();
4486*38e8c45fSAndroid Build Coastguard Worker return;
4487*38e8c45fSAndroid Build Coastguard Worker }
4488*38e8c45fSAndroid Build Coastguard Worker
4489*38e8c45fSAndroid Build Coastguard Worker uint32_t policyFlags = args.policyFlags;
4490*38e8c45fSAndroid Build Coastguard Worker int32_t flags = args.flags;
4491*38e8c45fSAndroid Build Coastguard Worker int32_t metaState = args.metaState;
4492*38e8c45fSAndroid Build Coastguard Worker // InputDispatcher tracks and generates key repeats on behalf of
4493*38e8c45fSAndroid Build Coastguard Worker // whatever notifies it, so repeatCount should always be set to 0
4494*38e8c45fSAndroid Build Coastguard Worker constexpr int32_t repeatCount = 0;
4495*38e8c45fSAndroid Build Coastguard Worker if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
4496*38e8c45fSAndroid Build Coastguard Worker policyFlags |= POLICY_FLAG_VIRTUAL;
4497*38e8c45fSAndroid Build Coastguard Worker flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
4498*38e8c45fSAndroid Build Coastguard Worker }
4499*38e8c45fSAndroid Build Coastguard Worker if (policyFlags & POLICY_FLAG_FUNCTION) {
4500*38e8c45fSAndroid Build Coastguard Worker metaState |= AMETA_FUNCTION_ON;
4501*38e8c45fSAndroid Build Coastguard Worker }
4502*38e8c45fSAndroid Build Coastguard Worker
4503*38e8c45fSAndroid Build Coastguard Worker policyFlags |= POLICY_FLAG_TRUSTED;
4504*38e8c45fSAndroid Build Coastguard Worker
4505*38e8c45fSAndroid Build Coastguard Worker int32_t keyCode = args.keyCode;
4506*38e8c45fSAndroid Build Coastguard Worker KeyEvent event;
4507*38e8c45fSAndroid Build Coastguard Worker event.initialize(args.id, args.deviceId, args.source, args.displayId, INVALID_HMAC, args.action,
4508*38e8c45fSAndroid Build Coastguard Worker flags, keyCode, args.scanCode, metaState, repeatCount, args.downTime,
4509*38e8c45fSAndroid Build Coastguard Worker args.eventTime);
4510*38e8c45fSAndroid Build Coastguard Worker
4511*38e8c45fSAndroid Build Coastguard Worker android::base::Timer t;
4512*38e8c45fSAndroid Build Coastguard Worker mPolicy.interceptKeyBeforeQueueing(event, /*byref*/ policyFlags);
4513*38e8c45fSAndroid Build Coastguard Worker if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
4514*38e8c45fSAndroid Build Coastguard Worker ALOGW("Excessive delay in interceptKeyBeforeQueueing; took %s ms",
4515*38e8c45fSAndroid Build Coastguard Worker std::to_string(t.duration().count()).c_str());
4516*38e8c45fSAndroid Build Coastguard Worker }
4517*38e8c45fSAndroid Build Coastguard Worker
4518*38e8c45fSAndroid Build Coastguard Worker bool needWake = false;
4519*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
4520*38e8c45fSAndroid Build Coastguard Worker mLock.lock();
4521*38e8c45fSAndroid Build Coastguard Worker
4522*38e8c45fSAndroid Build Coastguard Worker if (input_flags::keyboard_repeat_keys() && !mConfig.keyRepeatEnabled) {
4523*38e8c45fSAndroid Build Coastguard Worker policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
4524*38e8c45fSAndroid Build Coastguard Worker }
4525*38e8c45fSAndroid Build Coastguard Worker
4526*38e8c45fSAndroid Build Coastguard Worker if (shouldSendKeyToInputFilterLocked(args)) {
4527*38e8c45fSAndroid Build Coastguard Worker mLock.unlock();
4528*38e8c45fSAndroid Build Coastguard Worker
4529*38e8c45fSAndroid Build Coastguard Worker policyFlags |= POLICY_FLAG_FILTERED;
4530*38e8c45fSAndroid Build Coastguard Worker if (!mPolicy.filterInputEvent(event, policyFlags)) {
4531*38e8c45fSAndroid Build Coastguard Worker return; // event was consumed by the filter
4532*38e8c45fSAndroid Build Coastguard Worker }
4533*38e8c45fSAndroid Build Coastguard Worker
4534*38e8c45fSAndroid Build Coastguard Worker mLock.lock();
4535*38e8c45fSAndroid Build Coastguard Worker }
4536*38e8c45fSAndroid Build Coastguard Worker
4537*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<KeyEntry> newEntry =
4538*38e8c45fSAndroid Build Coastguard Worker std::make_unique<KeyEntry>(args.id, /*injectionState=*/nullptr, args.eventTime,
4539*38e8c45fSAndroid Build Coastguard Worker args.deviceId, args.source, args.displayId, policyFlags,
4540*38e8c45fSAndroid Build Coastguard Worker args.action, flags, keyCode, args.scanCode, metaState,
4541*38e8c45fSAndroid Build Coastguard Worker repeatCount, args.downTime);
4542*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
4543*38e8c45fSAndroid Build Coastguard Worker newEntry->traceTracker = mTracer->traceInboundEvent(*newEntry);
4544*38e8c45fSAndroid Build Coastguard Worker }
4545*38e8c45fSAndroid Build Coastguard Worker
4546*38e8c45fSAndroid Build Coastguard Worker if (mPerDeviceInputLatencyMetricsFlag) {
4547*38e8c45fSAndroid Build Coastguard Worker if (args.id != android::os::IInputConstants::INVALID_INPUT_EVENT_ID &&
4548*38e8c45fSAndroid Build Coastguard Worker IdGenerator::getSource(args.id) == IdGenerator::Source::INPUT_READER &&
4549*38e8c45fSAndroid Build Coastguard Worker !mInputFilterEnabled) {
4550*38e8c45fSAndroid Build Coastguard Worker mLatencyTracker.trackListener(args);
4551*38e8c45fSAndroid Build Coastguard Worker }
4552*38e8c45fSAndroid Build Coastguard Worker }
4553*38e8c45fSAndroid Build Coastguard Worker
4554*38e8c45fSAndroid Build Coastguard Worker needWake = enqueueInboundEventLocked(std::move(newEntry));
4555*38e8c45fSAndroid Build Coastguard Worker mLock.unlock();
4556*38e8c45fSAndroid Build Coastguard Worker } // release lock
4557*38e8c45fSAndroid Build Coastguard Worker
4558*38e8c45fSAndroid Build Coastguard Worker if (needWake) {
4559*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
4560*38e8c45fSAndroid Build Coastguard Worker }
4561*38e8c45fSAndroid Build Coastguard Worker }
4562*38e8c45fSAndroid Build Coastguard Worker
shouldSendKeyToInputFilterLocked(const NotifyKeyArgs & args)4563*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::shouldSendKeyToInputFilterLocked(const NotifyKeyArgs& args) {
4564*38e8c45fSAndroid Build Coastguard Worker return mInputFilterEnabled;
4565*38e8c45fSAndroid Build Coastguard Worker }
4566*38e8c45fSAndroid Build Coastguard Worker
notifyMotion(const NotifyMotionArgs & args)4567*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::notifyMotion(const NotifyMotionArgs& args) {
4568*38e8c45fSAndroid Build Coastguard Worker if (debugInboundEventDetails()) {
4569*38e8c45fSAndroid Build Coastguard Worker ALOGD("notifyMotion - id=%" PRIx32 " eventTime=%" PRId64 ", deviceId=%d, source=%s, "
4570*38e8c45fSAndroid Build Coastguard Worker "displayId=%s, policyFlags=0x%x, "
4571*38e8c45fSAndroid Build Coastguard Worker "action=%s, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, "
4572*38e8c45fSAndroid Build Coastguard Worker "xCursorPosition=%f, yCursorPosition=%f, downTime=%" PRId64,
4573*38e8c45fSAndroid Build Coastguard Worker args.id, args.eventTime, args.deviceId, inputEventSourceToString(args.source).c_str(),
4574*38e8c45fSAndroid Build Coastguard Worker args.displayId.toString().c_str(), args.policyFlags,
4575*38e8c45fSAndroid Build Coastguard Worker MotionEvent::actionToString(args.action).c_str(), args.actionButton, args.flags,
4576*38e8c45fSAndroid Build Coastguard Worker args.metaState, args.buttonState, args.xCursorPosition, args.yCursorPosition,
4577*38e8c45fSAndroid Build Coastguard Worker args.downTime);
4578*38e8c45fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < args.getPointerCount(); i++) {
4579*38e8c45fSAndroid Build Coastguard Worker ALOGD(" Pointer %d: id=%d, toolType=%s, x=%f, y=%f, pressure=%f, size=%f, "
4580*38e8c45fSAndroid Build Coastguard Worker "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, orientation=%f",
4581*38e8c45fSAndroid Build Coastguard Worker i, args.pointerProperties[i].id,
4582*38e8c45fSAndroid Build Coastguard Worker ftl::enum_string(args.pointerProperties[i].toolType).c_str(),
4583*38e8c45fSAndroid Build Coastguard Worker args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
4584*38e8c45fSAndroid Build Coastguard Worker args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
4585*38e8c45fSAndroid Build Coastguard Worker args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
4586*38e8c45fSAndroid Build Coastguard Worker args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
4587*38e8c45fSAndroid Build Coastguard Worker args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
4588*38e8c45fSAndroid Build Coastguard Worker args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
4589*38e8c45fSAndroid Build Coastguard Worker args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
4590*38e8c45fSAndroid Build Coastguard Worker args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
4591*38e8c45fSAndroid Build Coastguard Worker args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
4592*38e8c45fSAndroid Build Coastguard Worker }
4593*38e8c45fSAndroid Build Coastguard Worker }
4594*38e8c45fSAndroid Build Coastguard Worker
4595*38e8c45fSAndroid Build Coastguard Worker Result<void> motionCheck =
4596*38e8c45fSAndroid Build Coastguard Worker validateMotionEvent(args.action, args.actionButton, args.getPointerCount(),
4597*38e8c45fSAndroid Build Coastguard Worker args.pointerProperties.data());
4598*38e8c45fSAndroid Build Coastguard Worker if (!motionCheck.ok()) {
4599*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << "Invalid event: " << args.dump() << "; reason: " << motionCheck.error();
4600*38e8c45fSAndroid Build Coastguard Worker return;
4601*38e8c45fSAndroid Build Coastguard Worker }
4602*38e8c45fSAndroid Build Coastguard Worker
4603*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_VERIFY_EVENTS) {
4604*38e8c45fSAndroid Build Coastguard Worker auto [it, _] =
4605*38e8c45fSAndroid Build Coastguard Worker mVerifiersByDisplay.try_emplace(args.displayId,
4606*38e8c45fSAndroid Build Coastguard Worker StringPrintf("display %s",
4607*38e8c45fSAndroid Build Coastguard Worker args.displayId.toString().c_str()));
4608*38e8c45fSAndroid Build Coastguard Worker Result<void> result =
4609*38e8c45fSAndroid Build Coastguard Worker it->second.processMovement(args.deviceId, args.source, args.action,
4610*38e8c45fSAndroid Build Coastguard Worker args.getPointerCount(), args.pointerProperties.data(),
4611*38e8c45fSAndroid Build Coastguard Worker args.pointerCoords.data(), args.flags);
4612*38e8c45fSAndroid Build Coastguard Worker if (!result.ok()) {
4613*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << "Bad stream: " << result.error() << " caused by " << args.dump();
4614*38e8c45fSAndroid Build Coastguard Worker }
4615*38e8c45fSAndroid Build Coastguard Worker }
4616*38e8c45fSAndroid Build Coastguard Worker
4617*38e8c45fSAndroid Build Coastguard Worker uint32_t policyFlags = args.policyFlags;
4618*38e8c45fSAndroid Build Coastguard Worker policyFlags |= POLICY_FLAG_TRUSTED;
4619*38e8c45fSAndroid Build Coastguard Worker
4620*38e8c45fSAndroid Build Coastguard Worker android::base::Timer t;
4621*38e8c45fSAndroid Build Coastguard Worker mPolicy.interceptMotionBeforeQueueing(args.displayId, args.source, args.action, args.eventTime,
4622*38e8c45fSAndroid Build Coastguard Worker policyFlags);
4623*38e8c45fSAndroid Build Coastguard Worker if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
4624*38e8c45fSAndroid Build Coastguard Worker ALOGW("Excessive delay in interceptMotionBeforeQueueing; took %s ms",
4625*38e8c45fSAndroid Build Coastguard Worker std::to_string(t.duration().count()).c_str());
4626*38e8c45fSAndroid Build Coastguard Worker }
4627*38e8c45fSAndroid Build Coastguard Worker
4628*38e8c45fSAndroid Build Coastguard Worker bool needWake = false;
4629*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
4630*38e8c45fSAndroid Build Coastguard Worker mLock.lock();
4631*38e8c45fSAndroid Build Coastguard Worker if (!(policyFlags & POLICY_FLAG_PASS_TO_USER)) {
4632*38e8c45fSAndroid Build Coastguard Worker // Set the flag anyway if we already have an ongoing gesture. That would allow us to
4633*38e8c45fSAndroid Build Coastguard Worker // complete the processing of the current stroke.
4634*38e8c45fSAndroid Build Coastguard Worker const auto touchStateIt = mTouchStatesByDisplay.find(args.displayId);
4635*38e8c45fSAndroid Build Coastguard Worker if (touchStateIt != mTouchStatesByDisplay.end()) {
4636*38e8c45fSAndroid Build Coastguard Worker const TouchState& touchState = touchStateIt->second;
4637*38e8c45fSAndroid Build Coastguard Worker if (touchState.hasTouchingPointers(args.deviceId) ||
4638*38e8c45fSAndroid Build Coastguard Worker touchState.hasHoveringPointers(args.deviceId)) {
4639*38e8c45fSAndroid Build Coastguard Worker policyFlags |= POLICY_FLAG_PASS_TO_USER;
4640*38e8c45fSAndroid Build Coastguard Worker }
4641*38e8c45fSAndroid Build Coastguard Worker }
4642*38e8c45fSAndroid Build Coastguard Worker }
4643*38e8c45fSAndroid Build Coastguard Worker
4644*38e8c45fSAndroid Build Coastguard Worker if (shouldSendMotionToInputFilterLocked(args)) {
4645*38e8c45fSAndroid Build Coastguard Worker ui::Transform displayTransform;
4646*38e8c45fSAndroid Build Coastguard Worker if (const auto it = mDisplayInfos.find(args.displayId); it != mDisplayInfos.end()) {
4647*38e8c45fSAndroid Build Coastguard Worker displayTransform = it->second.transform;
4648*38e8c45fSAndroid Build Coastguard Worker }
4649*38e8c45fSAndroid Build Coastguard Worker
4650*38e8c45fSAndroid Build Coastguard Worker mLock.unlock();
4651*38e8c45fSAndroid Build Coastguard Worker
4652*38e8c45fSAndroid Build Coastguard Worker MotionEvent event;
4653*38e8c45fSAndroid Build Coastguard Worker event.initialize(args.id, args.deviceId, args.source, args.displayId, INVALID_HMAC,
4654*38e8c45fSAndroid Build Coastguard Worker args.action, args.actionButton, args.flags, args.edgeFlags,
4655*38e8c45fSAndroid Build Coastguard Worker args.metaState, args.buttonState, args.classification,
4656*38e8c45fSAndroid Build Coastguard Worker displayTransform, args.xPrecision, args.yPrecision,
4657*38e8c45fSAndroid Build Coastguard Worker args.xCursorPosition, args.yCursorPosition, displayTransform,
4658*38e8c45fSAndroid Build Coastguard Worker args.downTime, args.eventTime, args.getPointerCount(),
4659*38e8c45fSAndroid Build Coastguard Worker args.pointerProperties.data(), args.pointerCoords.data());
4660*38e8c45fSAndroid Build Coastguard Worker
4661*38e8c45fSAndroid Build Coastguard Worker policyFlags |= POLICY_FLAG_FILTERED;
4662*38e8c45fSAndroid Build Coastguard Worker if (!mPolicy.filterInputEvent(event, policyFlags)) {
4663*38e8c45fSAndroid Build Coastguard Worker return; // event was consumed by the filter
4664*38e8c45fSAndroid Build Coastguard Worker }
4665*38e8c45fSAndroid Build Coastguard Worker
4666*38e8c45fSAndroid Build Coastguard Worker mLock.lock();
4667*38e8c45fSAndroid Build Coastguard Worker }
4668*38e8c45fSAndroid Build Coastguard Worker
4669*38e8c45fSAndroid Build Coastguard Worker // Just enqueue a new motion event.
4670*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<MotionEntry> newEntry =
4671*38e8c45fSAndroid Build Coastguard Worker std::make_unique<MotionEntry>(args.id, /*injectionState=*/nullptr, args.eventTime,
4672*38e8c45fSAndroid Build Coastguard Worker args.deviceId, args.source, args.displayId,
4673*38e8c45fSAndroid Build Coastguard Worker policyFlags, args.action, args.actionButton,
4674*38e8c45fSAndroid Build Coastguard Worker args.flags, args.metaState, args.buttonState,
4675*38e8c45fSAndroid Build Coastguard Worker args.classification, args.edgeFlags, args.xPrecision,
4676*38e8c45fSAndroid Build Coastguard Worker args.yPrecision, args.xCursorPosition,
4677*38e8c45fSAndroid Build Coastguard Worker args.yCursorPosition, args.downTime,
4678*38e8c45fSAndroid Build Coastguard Worker args.pointerProperties, args.pointerCoords);
4679*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
4680*38e8c45fSAndroid Build Coastguard Worker newEntry->traceTracker = mTracer->traceInboundEvent(*newEntry);
4681*38e8c45fSAndroid Build Coastguard Worker }
4682*38e8c45fSAndroid Build Coastguard Worker
4683*38e8c45fSAndroid Build Coastguard Worker if (args.id != android::os::IInputConstants::INVALID_INPUT_EVENT_ID &&
4684*38e8c45fSAndroid Build Coastguard Worker IdGenerator::getSource(args.id) == IdGenerator::Source::INPUT_READER &&
4685*38e8c45fSAndroid Build Coastguard Worker !mInputFilterEnabled) {
4686*38e8c45fSAndroid Build Coastguard Worker mLatencyTracker.trackListener(args);
4687*38e8c45fSAndroid Build Coastguard Worker }
4688*38e8c45fSAndroid Build Coastguard Worker
4689*38e8c45fSAndroid Build Coastguard Worker needWake = enqueueInboundEventLocked(std::move(newEntry));
4690*38e8c45fSAndroid Build Coastguard Worker mLock.unlock();
4691*38e8c45fSAndroid Build Coastguard Worker } // release lock
4692*38e8c45fSAndroid Build Coastguard Worker
4693*38e8c45fSAndroid Build Coastguard Worker if (needWake) {
4694*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
4695*38e8c45fSAndroid Build Coastguard Worker }
4696*38e8c45fSAndroid Build Coastguard Worker }
4697*38e8c45fSAndroid Build Coastguard Worker
notifySensor(const NotifySensorArgs & args)4698*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::notifySensor(const NotifySensorArgs& args) {
4699*38e8c45fSAndroid Build Coastguard Worker if (debugInboundEventDetails()) {
4700*38e8c45fSAndroid Build Coastguard Worker ALOGD("notifySensor - id=%" PRIx32 " eventTime=%" PRId64 ", deviceId=%d, source=0x%x, "
4701*38e8c45fSAndroid Build Coastguard Worker " sensorType=%s",
4702*38e8c45fSAndroid Build Coastguard Worker args.id, args.eventTime, args.deviceId, args.source,
4703*38e8c45fSAndroid Build Coastguard Worker ftl::enum_string(args.sensorType).c_str());
4704*38e8c45fSAndroid Build Coastguard Worker }
4705*38e8c45fSAndroid Build Coastguard Worker
4706*38e8c45fSAndroid Build Coastguard Worker bool needWake = false;
4707*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
4708*38e8c45fSAndroid Build Coastguard Worker mLock.lock();
4709*38e8c45fSAndroid Build Coastguard Worker
4710*38e8c45fSAndroid Build Coastguard Worker // Just enqueue a new sensor event.
4711*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<SensorEntry> newEntry =
4712*38e8c45fSAndroid Build Coastguard Worker std::make_unique<SensorEntry>(args.id, args.eventTime, args.deviceId, args.source,
4713*38e8c45fSAndroid Build Coastguard Worker /* policyFlags=*/0, args.hwTimestamp, args.sensorType,
4714*38e8c45fSAndroid Build Coastguard Worker args.accuracy, args.accuracyChanged, args.values);
4715*38e8c45fSAndroid Build Coastguard Worker
4716*38e8c45fSAndroid Build Coastguard Worker needWake = enqueueInboundEventLocked(std::move(newEntry));
4717*38e8c45fSAndroid Build Coastguard Worker mLock.unlock();
4718*38e8c45fSAndroid Build Coastguard Worker } // release lock
4719*38e8c45fSAndroid Build Coastguard Worker
4720*38e8c45fSAndroid Build Coastguard Worker if (needWake) {
4721*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
4722*38e8c45fSAndroid Build Coastguard Worker }
4723*38e8c45fSAndroid Build Coastguard Worker }
4724*38e8c45fSAndroid Build Coastguard Worker
notifyVibratorState(const NotifyVibratorStateArgs & args)4725*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::notifyVibratorState(const NotifyVibratorStateArgs& args) {
4726*38e8c45fSAndroid Build Coastguard Worker if (debugInboundEventDetails()) {
4727*38e8c45fSAndroid Build Coastguard Worker ALOGD("notifyVibratorState - eventTime=%" PRId64 ", device=%d, isOn=%d", args.eventTime,
4728*38e8c45fSAndroid Build Coastguard Worker args.deviceId, args.isOn);
4729*38e8c45fSAndroid Build Coastguard Worker }
4730*38e8c45fSAndroid Build Coastguard Worker mPolicy.notifyVibratorState(args.deviceId, args.isOn);
4731*38e8c45fSAndroid Build Coastguard Worker }
4732*38e8c45fSAndroid Build Coastguard Worker
shouldSendMotionToInputFilterLocked(const NotifyMotionArgs & args)4733*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::shouldSendMotionToInputFilterLocked(const NotifyMotionArgs& args) {
4734*38e8c45fSAndroid Build Coastguard Worker return mInputFilterEnabled;
4735*38e8c45fSAndroid Build Coastguard Worker }
4736*38e8c45fSAndroid Build Coastguard Worker
notifySwitch(const NotifySwitchArgs & args)4737*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::notifySwitch(const NotifySwitchArgs& args) {
4738*38e8c45fSAndroid Build Coastguard Worker if (debugInboundEventDetails()) {
4739*38e8c45fSAndroid Build Coastguard Worker ALOGD("notifySwitch - eventTime=%" PRId64 ", policyFlags=0x%x, switchValues=0x%08x, "
4740*38e8c45fSAndroid Build Coastguard Worker "switchMask=0x%08x",
4741*38e8c45fSAndroid Build Coastguard Worker args.eventTime, args.policyFlags, args.switchValues, args.switchMask);
4742*38e8c45fSAndroid Build Coastguard Worker }
4743*38e8c45fSAndroid Build Coastguard Worker
4744*38e8c45fSAndroid Build Coastguard Worker uint32_t policyFlags = args.policyFlags;
4745*38e8c45fSAndroid Build Coastguard Worker policyFlags |= POLICY_FLAG_TRUSTED;
4746*38e8c45fSAndroid Build Coastguard Worker mPolicy.notifySwitch(args.eventTime, args.switchValues, args.switchMask, policyFlags);
4747*38e8c45fSAndroid Build Coastguard Worker }
4748*38e8c45fSAndroid Build Coastguard Worker
notifyDeviceReset(const NotifyDeviceResetArgs & args)4749*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
4750*38e8c45fSAndroid Build Coastguard Worker // TODO(b/308677868) Remove device reset from the InputListener interface
4751*38e8c45fSAndroid Build Coastguard Worker if (debugInboundEventDetails()) {
4752*38e8c45fSAndroid Build Coastguard Worker ALOGD("notifyDeviceReset - eventTime=%" PRId64 ", deviceId=%d", args.eventTime,
4753*38e8c45fSAndroid Build Coastguard Worker args.deviceId);
4754*38e8c45fSAndroid Build Coastguard Worker }
4755*38e8c45fSAndroid Build Coastguard Worker
4756*38e8c45fSAndroid Build Coastguard Worker bool needWake = false;
4757*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
4758*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
4759*38e8c45fSAndroid Build Coastguard Worker
4760*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<DeviceResetEntry> newEntry =
4761*38e8c45fSAndroid Build Coastguard Worker std::make_unique<DeviceResetEntry>(args.id, args.eventTime, args.deviceId);
4762*38e8c45fSAndroid Build Coastguard Worker needWake = enqueueInboundEventLocked(std::move(newEntry));
4763*38e8c45fSAndroid Build Coastguard Worker
4764*38e8c45fSAndroid Build Coastguard Worker for (auto& [_, verifier] : mVerifiersByDisplay) {
4765*38e8c45fSAndroid Build Coastguard Worker verifier.resetDevice(args.deviceId);
4766*38e8c45fSAndroid Build Coastguard Worker }
4767*38e8c45fSAndroid Build Coastguard Worker } // release lock
4768*38e8c45fSAndroid Build Coastguard Worker
4769*38e8c45fSAndroid Build Coastguard Worker if (needWake) {
4770*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
4771*38e8c45fSAndroid Build Coastguard Worker }
4772*38e8c45fSAndroid Build Coastguard Worker }
4773*38e8c45fSAndroid Build Coastguard Worker
notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs & args)4774*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) {
4775*38e8c45fSAndroid Build Coastguard Worker if (debugInboundEventDetails()) {
4776*38e8c45fSAndroid Build Coastguard Worker ALOGD("notifyPointerCaptureChanged - eventTime=%" PRId64 ", enabled=%s", args.eventTime,
4777*38e8c45fSAndroid Build Coastguard Worker args.request.isEnable() ? "true" : "false");
4778*38e8c45fSAndroid Build Coastguard Worker }
4779*38e8c45fSAndroid Build Coastguard Worker
4780*38e8c45fSAndroid Build Coastguard Worker bool needWake = false;
4781*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
4782*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
4783*38e8c45fSAndroid Build Coastguard Worker auto entry =
4784*38e8c45fSAndroid Build Coastguard Worker std::make_unique<PointerCaptureChangedEntry>(args.id, args.eventTime, args.request);
4785*38e8c45fSAndroid Build Coastguard Worker needWake = enqueueInboundEventLocked(std::move(entry));
4786*38e8c45fSAndroid Build Coastguard Worker } // release lock
4787*38e8c45fSAndroid Build Coastguard Worker
4788*38e8c45fSAndroid Build Coastguard Worker if (needWake) {
4789*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
4790*38e8c45fSAndroid Build Coastguard Worker }
4791*38e8c45fSAndroid Build Coastguard Worker }
4792*38e8c45fSAndroid Build Coastguard Worker
shouldRejectInjectedMotionLocked(const MotionEvent & motionEvent,DeviceId deviceId,ui::LogicalDisplayId displayId,std::optional<gui::Uid> targetUid,int32_t flags)4793*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::shouldRejectInjectedMotionLocked(const MotionEvent& motionEvent,
4794*38e8c45fSAndroid Build Coastguard Worker DeviceId deviceId,
4795*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId displayId,
4796*38e8c45fSAndroid Build Coastguard Worker std::optional<gui::Uid> targetUid,
4797*38e8c45fSAndroid Build Coastguard Worker int32_t flags) {
4798*38e8c45fSAndroid Build Coastguard Worker // Don't verify targeted injection, since it will only affect the caller's
4799*38e8c45fSAndroid Build Coastguard Worker // window, and the windows are typically destroyed at the end of the test.
4800*38e8c45fSAndroid Build Coastguard Worker if (targetUid.has_value()) {
4801*38e8c45fSAndroid Build Coastguard Worker return false;
4802*38e8c45fSAndroid Build Coastguard Worker }
4803*38e8c45fSAndroid Build Coastguard Worker
4804*38e8c45fSAndroid Build Coastguard Worker // Verify all other injected streams, whether the injection is coming from apps or from
4805*38e8c45fSAndroid Build Coastguard Worker // input filter. Print an error if the stream becomes inconsistent with this event.
4806*38e8c45fSAndroid Build Coastguard Worker // An inconsistent injected event sent could cause a crash in the later stages of
4807*38e8c45fSAndroid Build Coastguard Worker // dispatching pipeline.
4808*38e8c45fSAndroid Build Coastguard Worker auto [it, _] = mInputFilterVerifiersByDisplay.try_emplace(displayId,
4809*38e8c45fSAndroid Build Coastguard Worker std::string("Injection on ") +
4810*38e8c45fSAndroid Build Coastguard Worker displayId.toString());
4811*38e8c45fSAndroid Build Coastguard Worker InputVerifier& verifier = it->second;
4812*38e8c45fSAndroid Build Coastguard Worker
4813*38e8c45fSAndroid Build Coastguard Worker Result<void> result =
4814*38e8c45fSAndroid Build Coastguard Worker verifier.processMovement(deviceId, motionEvent.getSource(), motionEvent.getAction(),
4815*38e8c45fSAndroid Build Coastguard Worker motionEvent.getPointerCount(),
4816*38e8c45fSAndroid Build Coastguard Worker motionEvent.getPointerProperties(),
4817*38e8c45fSAndroid Build Coastguard Worker motionEvent.getSamplePointerCoords(), flags);
4818*38e8c45fSAndroid Build Coastguard Worker if (!result.ok()) {
4819*38e8c45fSAndroid Build Coastguard Worker logDispatchStateLocked();
4820*38e8c45fSAndroid Build Coastguard Worker LOG(ERROR) << "Inconsistent event: " << motionEvent << ", reason: " << result.error();
4821*38e8c45fSAndroid Build Coastguard Worker return true;
4822*38e8c45fSAndroid Build Coastguard Worker }
4823*38e8c45fSAndroid Build Coastguard Worker return false;
4824*38e8c45fSAndroid Build Coastguard Worker }
4825*38e8c45fSAndroid Build Coastguard Worker
injectInputEvent(const InputEvent * event,std::optional<gui::Uid> targetUid,InputEventInjectionSync syncMode,std::chrono::milliseconds timeout,uint32_t policyFlags)4826*38e8c45fSAndroid Build Coastguard Worker InputEventInjectionResult InputDispatcher::injectInputEvent(const InputEvent* event,
4827*38e8c45fSAndroid Build Coastguard Worker std::optional<gui::Uid> targetUid,
4828*38e8c45fSAndroid Build Coastguard Worker InputEventInjectionSync syncMode,
4829*38e8c45fSAndroid Build Coastguard Worker std::chrono::milliseconds timeout,
4830*38e8c45fSAndroid Build Coastguard Worker uint32_t policyFlags) {
4831*38e8c45fSAndroid Build Coastguard Worker Result<void> eventValidation = validateInputEvent(*event);
4832*38e8c45fSAndroid Build Coastguard Worker if (!eventValidation.ok()) {
4833*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "Injection failed: invalid event: " << eventValidation.error();
4834*38e8c45fSAndroid Build Coastguard Worker return InputEventInjectionResult::FAILED;
4835*38e8c45fSAndroid Build Coastguard Worker }
4836*38e8c45fSAndroid Build Coastguard Worker
4837*38e8c45fSAndroid Build Coastguard Worker if (debugInboundEventDetails()) {
4838*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << __func__ << ": targetUid=" << toString(targetUid, &uidString)
4839*38e8c45fSAndroid Build Coastguard Worker << ", syncMode=" << ftl::enum_string(syncMode) << ", timeout=" << timeout.count()
4840*38e8c45fSAndroid Build Coastguard Worker << "ms, policyFlags=0x" << std::hex << policyFlags << std::dec
4841*38e8c45fSAndroid Build Coastguard Worker << ", event=" << *event;
4842*38e8c45fSAndroid Build Coastguard Worker }
4843*38e8c45fSAndroid Build Coastguard Worker nsecs_t endTime = now() + std::chrono::duration_cast<std::chrono::nanoseconds>(timeout).count();
4844*38e8c45fSAndroid Build Coastguard Worker
4845*38e8c45fSAndroid Build Coastguard Worker policyFlags |= POLICY_FLAG_INJECTED | POLICY_FLAG_TRUSTED;
4846*38e8c45fSAndroid Build Coastguard Worker
4847*38e8c45fSAndroid Build Coastguard Worker // For all injected events, set device id = VIRTUAL_KEYBOARD_ID. The only exception is events
4848*38e8c45fSAndroid Build Coastguard Worker // that have gone through the InputFilter. If the event passed through the InputFilter, assign
4849*38e8c45fSAndroid Build Coastguard Worker // the provided device id. If the InputFilter is accessibility, and it modifies or synthesizes
4850*38e8c45fSAndroid Build Coastguard Worker // the injected event, it is responsible for setting POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY.
4851*38e8c45fSAndroid Build Coastguard Worker // For those events, we will set FLAG_IS_ACCESSIBILITY_EVENT to allow apps to distinguish them
4852*38e8c45fSAndroid Build Coastguard Worker // from events that originate from actual hardware.
4853*38e8c45fSAndroid Build Coastguard Worker DeviceId resolvedDeviceId = VIRTUAL_KEYBOARD_ID;
4854*38e8c45fSAndroid Build Coastguard Worker if (policyFlags & POLICY_FLAG_FILTERED) {
4855*38e8c45fSAndroid Build Coastguard Worker resolvedDeviceId = event->getDeviceId();
4856*38e8c45fSAndroid Build Coastguard Worker }
4857*38e8c45fSAndroid Build Coastguard Worker
4858*38e8c45fSAndroid Build Coastguard Worker const bool isAsync = syncMode == InputEventInjectionSync::NONE;
4859*38e8c45fSAndroid Build Coastguard Worker auto injectionState = std::make_shared<InjectionState>(targetUid, isAsync);
4860*38e8c45fSAndroid Build Coastguard Worker
4861*38e8c45fSAndroid Build Coastguard Worker std::queue<std::unique_ptr<EventEntry>> injectedEntries;
4862*38e8c45fSAndroid Build Coastguard Worker switch (event->getType()) {
4863*38e8c45fSAndroid Build Coastguard Worker case InputEventType::KEY: {
4864*38e8c45fSAndroid Build Coastguard Worker const KeyEvent& incomingKey = static_cast<const KeyEvent&>(*event);
4865*38e8c45fSAndroid Build Coastguard Worker const int32_t action = incomingKey.getAction();
4866*38e8c45fSAndroid Build Coastguard Worker int32_t flags = incomingKey.getFlags();
4867*38e8c45fSAndroid Build Coastguard Worker if (policyFlags & POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY) {
4868*38e8c45fSAndroid Build Coastguard Worker flags |= AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT;
4869*38e8c45fSAndroid Build Coastguard Worker }
4870*38e8c45fSAndroid Build Coastguard Worker int32_t keyCode = incomingKey.getKeyCode();
4871*38e8c45fSAndroid Build Coastguard Worker int32_t metaState = incomingKey.getMetaState();
4872*38e8c45fSAndroid Build Coastguard Worker KeyEvent keyEvent;
4873*38e8c45fSAndroid Build Coastguard Worker keyEvent.initialize(incomingKey.getId(), resolvedDeviceId, incomingKey.getSource(),
4874*38e8c45fSAndroid Build Coastguard Worker incomingKey.getDisplayId(), INVALID_HMAC, action, flags, keyCode,
4875*38e8c45fSAndroid Build Coastguard Worker incomingKey.getScanCode(), metaState, incomingKey.getRepeatCount(),
4876*38e8c45fSAndroid Build Coastguard Worker incomingKey.getDownTime(), incomingKey.getEventTime());
4877*38e8c45fSAndroid Build Coastguard Worker
4878*38e8c45fSAndroid Build Coastguard Worker if (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY) {
4879*38e8c45fSAndroid Build Coastguard Worker policyFlags |= POLICY_FLAG_VIRTUAL;
4880*38e8c45fSAndroid Build Coastguard Worker }
4881*38e8c45fSAndroid Build Coastguard Worker
4882*38e8c45fSAndroid Build Coastguard Worker if (!(policyFlags & POLICY_FLAG_FILTERED)) {
4883*38e8c45fSAndroid Build Coastguard Worker android::base::Timer t;
4884*38e8c45fSAndroid Build Coastguard Worker mPolicy.interceptKeyBeforeQueueing(keyEvent, /*byref*/ policyFlags);
4885*38e8c45fSAndroid Build Coastguard Worker if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
4886*38e8c45fSAndroid Build Coastguard Worker ALOGW("Excessive delay in interceptKeyBeforeQueueing; took %s ms",
4887*38e8c45fSAndroid Build Coastguard Worker std::to_string(t.duration().count()).c_str());
4888*38e8c45fSAndroid Build Coastguard Worker }
4889*38e8c45fSAndroid Build Coastguard Worker }
4890*38e8c45fSAndroid Build Coastguard Worker
4891*38e8c45fSAndroid Build Coastguard Worker mLock.lock();
4892*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<KeyEntry> injectedEntry =
4893*38e8c45fSAndroid Build Coastguard Worker std::make_unique<KeyEntry>(incomingKey.getId(), injectionState,
4894*38e8c45fSAndroid Build Coastguard Worker incomingKey.getEventTime(), resolvedDeviceId,
4895*38e8c45fSAndroid Build Coastguard Worker incomingKey.getSource(), incomingKey.getDisplayId(),
4896*38e8c45fSAndroid Build Coastguard Worker policyFlags, action, flags, keyCode,
4897*38e8c45fSAndroid Build Coastguard Worker incomingKey.getScanCode(), metaState,
4898*38e8c45fSAndroid Build Coastguard Worker incomingKey.getRepeatCount(),
4899*38e8c45fSAndroid Build Coastguard Worker incomingKey.getDownTime());
4900*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
4901*38e8c45fSAndroid Build Coastguard Worker injectedEntry->traceTracker = mTracer->traceInboundEvent(*injectedEntry);
4902*38e8c45fSAndroid Build Coastguard Worker }
4903*38e8c45fSAndroid Build Coastguard Worker injectedEntries.push(std::move(injectedEntry));
4904*38e8c45fSAndroid Build Coastguard Worker break;
4905*38e8c45fSAndroid Build Coastguard Worker }
4906*38e8c45fSAndroid Build Coastguard Worker
4907*38e8c45fSAndroid Build Coastguard Worker case InputEventType::MOTION: {
4908*38e8c45fSAndroid Build Coastguard Worker const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
4909*38e8c45fSAndroid Build Coastguard Worker const bool isPointerEvent =
4910*38e8c45fSAndroid Build Coastguard Worker isFromSource(event->getSource(), AINPUT_SOURCE_CLASS_POINTER);
4911*38e8c45fSAndroid Build Coastguard Worker // If a pointer event has no displayId specified, inject it to the default display.
4912*38e8c45fSAndroid Build Coastguard Worker const ui::LogicalDisplayId displayId =
4913*38e8c45fSAndroid Build Coastguard Worker isPointerEvent && (event->getDisplayId() == ui::LogicalDisplayId::INVALID)
4914*38e8c45fSAndroid Build Coastguard Worker ? ui::LogicalDisplayId::DEFAULT
4915*38e8c45fSAndroid Build Coastguard Worker : event->getDisplayId();
4916*38e8c45fSAndroid Build Coastguard Worker int32_t flags = motionEvent.getFlags();
4917*38e8c45fSAndroid Build Coastguard Worker
4918*38e8c45fSAndroid Build Coastguard Worker if (!(policyFlags & POLICY_FLAG_FILTERED)) {
4919*38e8c45fSAndroid Build Coastguard Worker nsecs_t eventTime = motionEvent.getEventTime();
4920*38e8c45fSAndroid Build Coastguard Worker android::base::Timer t;
4921*38e8c45fSAndroid Build Coastguard Worker mPolicy.interceptMotionBeforeQueueing(displayId, motionEvent.getSource(),
4922*38e8c45fSAndroid Build Coastguard Worker motionEvent.getAction(), eventTime,
4923*38e8c45fSAndroid Build Coastguard Worker /*byref*/ policyFlags);
4924*38e8c45fSAndroid Build Coastguard Worker if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
4925*38e8c45fSAndroid Build Coastguard Worker ALOGW("Excessive delay in interceptMotionBeforeQueueing; took %s ms",
4926*38e8c45fSAndroid Build Coastguard Worker std::to_string(t.duration().count()).c_str());
4927*38e8c45fSAndroid Build Coastguard Worker }
4928*38e8c45fSAndroid Build Coastguard Worker }
4929*38e8c45fSAndroid Build Coastguard Worker
4930*38e8c45fSAndroid Build Coastguard Worker if (policyFlags & POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY) {
4931*38e8c45fSAndroid Build Coastguard Worker flags |= AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT;
4932*38e8c45fSAndroid Build Coastguard Worker }
4933*38e8c45fSAndroid Build Coastguard Worker
4934*38e8c45fSAndroid Build Coastguard Worker mLock.lock();
4935*38e8c45fSAndroid Build Coastguard Worker
4936*38e8c45fSAndroid Build Coastguard Worker if (shouldRejectInjectedMotionLocked(motionEvent, resolvedDeviceId, displayId,
4937*38e8c45fSAndroid Build Coastguard Worker targetUid, flags)) {
4938*38e8c45fSAndroid Build Coastguard Worker mLock.unlock();
4939*38e8c45fSAndroid Build Coastguard Worker return InputEventInjectionResult::FAILED;
4940*38e8c45fSAndroid Build Coastguard Worker }
4941*38e8c45fSAndroid Build Coastguard Worker
4942*38e8c45fSAndroid Build Coastguard Worker const nsecs_t* sampleEventTimes = motionEvent.getSampleEventTimes();
4943*38e8c45fSAndroid Build Coastguard Worker const size_t pointerCount = motionEvent.getPointerCount();
4944*38e8c45fSAndroid Build Coastguard Worker const std::vector<PointerProperties>
4945*38e8c45fSAndroid Build Coastguard Worker pointerProperties(motionEvent.getPointerProperties(),
4946*38e8c45fSAndroid Build Coastguard Worker motionEvent.getPointerProperties() + pointerCount);
4947*38e8c45fSAndroid Build Coastguard Worker
4948*38e8c45fSAndroid Build Coastguard Worker const PointerCoords* samplePointerCoords = motionEvent.getSamplePointerCoords();
4949*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<MotionEntry> injectedEntry =
4950*38e8c45fSAndroid Build Coastguard Worker std::make_unique<MotionEntry>(motionEvent.getId(), injectionState,
4951*38e8c45fSAndroid Build Coastguard Worker *sampleEventTimes, resolvedDeviceId,
4952*38e8c45fSAndroid Build Coastguard Worker motionEvent.getSource(), displayId, policyFlags,
4953*38e8c45fSAndroid Build Coastguard Worker motionEvent.getAction(),
4954*38e8c45fSAndroid Build Coastguard Worker motionEvent.getActionButton(), flags,
4955*38e8c45fSAndroid Build Coastguard Worker motionEvent.getMetaState(),
4956*38e8c45fSAndroid Build Coastguard Worker motionEvent.getButtonState(),
4957*38e8c45fSAndroid Build Coastguard Worker motionEvent.getClassification(),
4958*38e8c45fSAndroid Build Coastguard Worker motionEvent.getEdgeFlags(),
4959*38e8c45fSAndroid Build Coastguard Worker motionEvent.getXPrecision(),
4960*38e8c45fSAndroid Build Coastguard Worker motionEvent.getYPrecision(),
4961*38e8c45fSAndroid Build Coastguard Worker motionEvent.getRawXCursorPosition(),
4962*38e8c45fSAndroid Build Coastguard Worker motionEvent.getRawYCursorPosition(),
4963*38e8c45fSAndroid Build Coastguard Worker motionEvent.getDownTime(), pointerProperties,
4964*38e8c45fSAndroid Build Coastguard Worker std::vector<PointerCoords>(samplePointerCoords,
4965*38e8c45fSAndroid Build Coastguard Worker samplePointerCoords +
4966*38e8c45fSAndroid Build Coastguard Worker pointerCount));
4967*38e8c45fSAndroid Build Coastguard Worker transformMotionEntryForInjectionLocked(*injectedEntry, motionEvent.getTransform());
4968*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
4969*38e8c45fSAndroid Build Coastguard Worker injectedEntry->traceTracker = mTracer->traceInboundEvent(*injectedEntry);
4970*38e8c45fSAndroid Build Coastguard Worker }
4971*38e8c45fSAndroid Build Coastguard Worker injectedEntries.push(std::move(injectedEntry));
4972*38e8c45fSAndroid Build Coastguard Worker for (size_t i = motionEvent.getHistorySize(); i > 0; i--) {
4973*38e8c45fSAndroid Build Coastguard Worker sampleEventTimes += 1;
4974*38e8c45fSAndroid Build Coastguard Worker samplePointerCoords += motionEvent.getPointerCount();
4975*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<MotionEntry> nextInjectedEntry = std::make_unique<
4976*38e8c45fSAndroid Build Coastguard Worker MotionEntry>(motionEvent.getId(), injectionState, *sampleEventTimes,
4977*38e8c45fSAndroid Build Coastguard Worker resolvedDeviceId, motionEvent.getSource(), displayId,
4978*38e8c45fSAndroid Build Coastguard Worker policyFlags, motionEvent.getAction(),
4979*38e8c45fSAndroid Build Coastguard Worker motionEvent.getActionButton(), flags,
4980*38e8c45fSAndroid Build Coastguard Worker motionEvent.getMetaState(), motionEvent.getButtonState(),
4981*38e8c45fSAndroid Build Coastguard Worker motionEvent.getClassification(), motionEvent.getEdgeFlags(),
4982*38e8c45fSAndroid Build Coastguard Worker motionEvent.getXPrecision(), motionEvent.getYPrecision(),
4983*38e8c45fSAndroid Build Coastguard Worker motionEvent.getRawXCursorPosition(),
4984*38e8c45fSAndroid Build Coastguard Worker motionEvent.getRawYCursorPosition(), motionEvent.getDownTime(),
4985*38e8c45fSAndroid Build Coastguard Worker pointerProperties,
4986*38e8c45fSAndroid Build Coastguard Worker std::vector<PointerCoords>(samplePointerCoords,
4987*38e8c45fSAndroid Build Coastguard Worker samplePointerCoords +
4988*38e8c45fSAndroid Build Coastguard Worker pointerCount));
4989*38e8c45fSAndroid Build Coastguard Worker transformMotionEntryForInjectionLocked(*nextInjectedEntry,
4990*38e8c45fSAndroid Build Coastguard Worker motionEvent.getTransform());
4991*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
4992*38e8c45fSAndroid Build Coastguard Worker nextInjectedEntry->traceTracker =
4993*38e8c45fSAndroid Build Coastguard Worker mTracer->traceInboundEvent(*nextInjectedEntry);
4994*38e8c45fSAndroid Build Coastguard Worker }
4995*38e8c45fSAndroid Build Coastguard Worker injectedEntries.push(std::move(nextInjectedEntry));
4996*38e8c45fSAndroid Build Coastguard Worker }
4997*38e8c45fSAndroid Build Coastguard Worker break;
4998*38e8c45fSAndroid Build Coastguard Worker }
4999*38e8c45fSAndroid Build Coastguard Worker
5000*38e8c45fSAndroid Build Coastguard Worker default:
5001*38e8c45fSAndroid Build Coastguard Worker LOG(WARNING) << "Cannot inject " << ftl::enum_string(event->getType()) << " events";
5002*38e8c45fSAndroid Build Coastguard Worker return InputEventInjectionResult::FAILED;
5003*38e8c45fSAndroid Build Coastguard Worker }
5004*38e8c45fSAndroid Build Coastguard Worker
5005*38e8c45fSAndroid Build Coastguard Worker bool needWake = false;
5006*38e8c45fSAndroid Build Coastguard Worker while (!injectedEntries.empty()) {
5007*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_INJECTION) {
5008*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "Injecting " << injectedEntries.front()->getDescription();
5009*38e8c45fSAndroid Build Coastguard Worker }
5010*38e8c45fSAndroid Build Coastguard Worker needWake |= enqueueInboundEventLocked(std::move(injectedEntries.front()));
5011*38e8c45fSAndroid Build Coastguard Worker injectedEntries.pop();
5012*38e8c45fSAndroid Build Coastguard Worker }
5013*38e8c45fSAndroid Build Coastguard Worker
5014*38e8c45fSAndroid Build Coastguard Worker mLock.unlock();
5015*38e8c45fSAndroid Build Coastguard Worker
5016*38e8c45fSAndroid Build Coastguard Worker if (needWake) {
5017*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
5018*38e8c45fSAndroid Build Coastguard Worker }
5019*38e8c45fSAndroid Build Coastguard Worker
5020*38e8c45fSAndroid Build Coastguard Worker InputEventInjectionResult injectionResult;
5021*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
5022*38e8c45fSAndroid Build Coastguard Worker std::unique_lock _l(mLock);
5023*38e8c45fSAndroid Build Coastguard Worker
5024*38e8c45fSAndroid Build Coastguard Worker if (syncMode == InputEventInjectionSync::NONE) {
5025*38e8c45fSAndroid Build Coastguard Worker injectionResult = InputEventInjectionResult::SUCCEEDED;
5026*38e8c45fSAndroid Build Coastguard Worker } else {
5027*38e8c45fSAndroid Build Coastguard Worker for (;;) {
5028*38e8c45fSAndroid Build Coastguard Worker injectionResult = injectionState->injectionResult;
5029*38e8c45fSAndroid Build Coastguard Worker if (injectionResult != InputEventInjectionResult::PENDING) {
5030*38e8c45fSAndroid Build Coastguard Worker break;
5031*38e8c45fSAndroid Build Coastguard Worker }
5032*38e8c45fSAndroid Build Coastguard Worker
5033*38e8c45fSAndroid Build Coastguard Worker nsecs_t remainingTimeout = endTime - now();
5034*38e8c45fSAndroid Build Coastguard Worker if (remainingTimeout <= 0) {
5035*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_INJECTION) {
5036*38e8c45fSAndroid Build Coastguard Worker ALOGD("injectInputEvent - Timed out waiting for injection result "
5037*38e8c45fSAndroid Build Coastguard Worker "to become available.");
5038*38e8c45fSAndroid Build Coastguard Worker }
5039*38e8c45fSAndroid Build Coastguard Worker injectionResult = InputEventInjectionResult::TIMED_OUT;
5040*38e8c45fSAndroid Build Coastguard Worker break;
5041*38e8c45fSAndroid Build Coastguard Worker }
5042*38e8c45fSAndroid Build Coastguard Worker
5043*38e8c45fSAndroid Build Coastguard Worker mInjectionResultAvailable.wait_for(_l, std::chrono::nanoseconds(remainingTimeout));
5044*38e8c45fSAndroid Build Coastguard Worker }
5045*38e8c45fSAndroid Build Coastguard Worker
5046*38e8c45fSAndroid Build Coastguard Worker if (injectionResult == InputEventInjectionResult::SUCCEEDED &&
5047*38e8c45fSAndroid Build Coastguard Worker syncMode == InputEventInjectionSync::WAIT_FOR_FINISHED) {
5048*38e8c45fSAndroid Build Coastguard Worker while (injectionState->pendingForegroundDispatches != 0) {
5049*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_INJECTION) {
5050*38e8c45fSAndroid Build Coastguard Worker ALOGD("injectInputEvent - Waiting for %d pending foreground dispatches.",
5051*38e8c45fSAndroid Build Coastguard Worker injectionState->pendingForegroundDispatches);
5052*38e8c45fSAndroid Build Coastguard Worker }
5053*38e8c45fSAndroid Build Coastguard Worker nsecs_t remainingTimeout = endTime - now();
5054*38e8c45fSAndroid Build Coastguard Worker if (remainingTimeout <= 0) {
5055*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_INJECTION) {
5056*38e8c45fSAndroid Build Coastguard Worker ALOGD("injectInputEvent - Timed out waiting for pending foreground "
5057*38e8c45fSAndroid Build Coastguard Worker "dispatches to finish.");
5058*38e8c45fSAndroid Build Coastguard Worker }
5059*38e8c45fSAndroid Build Coastguard Worker injectionResult = InputEventInjectionResult::TIMED_OUT;
5060*38e8c45fSAndroid Build Coastguard Worker break;
5061*38e8c45fSAndroid Build Coastguard Worker }
5062*38e8c45fSAndroid Build Coastguard Worker
5063*38e8c45fSAndroid Build Coastguard Worker mInjectionSyncFinished.wait_for(_l, std::chrono::nanoseconds(remainingTimeout));
5064*38e8c45fSAndroid Build Coastguard Worker }
5065*38e8c45fSAndroid Build Coastguard Worker }
5066*38e8c45fSAndroid Build Coastguard Worker }
5067*38e8c45fSAndroid Build Coastguard Worker } // release lock
5068*38e8c45fSAndroid Build Coastguard Worker
5069*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_INJECTION) {
5070*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "injectInputEvent - Finished with result "
5071*38e8c45fSAndroid Build Coastguard Worker << ftl::enum_string(injectionResult);
5072*38e8c45fSAndroid Build Coastguard Worker }
5073*38e8c45fSAndroid Build Coastguard Worker
5074*38e8c45fSAndroid Build Coastguard Worker return injectionResult;
5075*38e8c45fSAndroid Build Coastguard Worker }
5076*38e8c45fSAndroid Build Coastguard Worker
verifyInputEvent(const InputEvent & event)5077*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<VerifiedInputEvent> InputDispatcher::verifyInputEvent(const InputEvent& event) {
5078*38e8c45fSAndroid Build Coastguard Worker std::array<uint8_t, 32> calculatedHmac;
5079*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<VerifiedInputEvent> result;
5080*38e8c45fSAndroid Build Coastguard Worker switch (event.getType()) {
5081*38e8c45fSAndroid Build Coastguard Worker case InputEventType::KEY: {
5082*38e8c45fSAndroid Build Coastguard Worker const KeyEvent& keyEvent = static_cast<const KeyEvent&>(event);
5083*38e8c45fSAndroid Build Coastguard Worker VerifiedKeyEvent verifiedKeyEvent = verifiedKeyEventFromKeyEvent(keyEvent);
5084*38e8c45fSAndroid Build Coastguard Worker result = std::make_unique<VerifiedKeyEvent>(verifiedKeyEvent);
5085*38e8c45fSAndroid Build Coastguard Worker calculatedHmac = sign(verifiedKeyEvent);
5086*38e8c45fSAndroid Build Coastguard Worker break;
5087*38e8c45fSAndroid Build Coastguard Worker }
5088*38e8c45fSAndroid Build Coastguard Worker case InputEventType::MOTION: {
5089*38e8c45fSAndroid Build Coastguard Worker const MotionEvent& motionEvent = static_cast<const MotionEvent&>(event);
5090*38e8c45fSAndroid Build Coastguard Worker VerifiedMotionEvent verifiedMotionEvent =
5091*38e8c45fSAndroid Build Coastguard Worker verifiedMotionEventFromMotionEvent(motionEvent);
5092*38e8c45fSAndroid Build Coastguard Worker result = std::make_unique<VerifiedMotionEvent>(verifiedMotionEvent);
5093*38e8c45fSAndroid Build Coastguard Worker calculatedHmac = sign(verifiedMotionEvent);
5094*38e8c45fSAndroid Build Coastguard Worker break;
5095*38e8c45fSAndroid Build Coastguard Worker }
5096*38e8c45fSAndroid Build Coastguard Worker default: {
5097*38e8c45fSAndroid Build Coastguard Worker LOG(ERROR) << "Cannot verify events of type " << ftl::enum_string(event.getType());
5098*38e8c45fSAndroid Build Coastguard Worker return nullptr;
5099*38e8c45fSAndroid Build Coastguard Worker }
5100*38e8c45fSAndroid Build Coastguard Worker }
5101*38e8c45fSAndroid Build Coastguard Worker if (calculatedHmac == INVALID_HMAC) {
5102*38e8c45fSAndroid Build Coastguard Worker return nullptr;
5103*38e8c45fSAndroid Build Coastguard Worker }
5104*38e8c45fSAndroid Build Coastguard Worker if (0 != CRYPTO_memcmp(calculatedHmac.data(), event.getHmac().data(), calculatedHmac.size())) {
5105*38e8c45fSAndroid Build Coastguard Worker return nullptr;
5106*38e8c45fSAndroid Build Coastguard Worker }
5107*38e8c45fSAndroid Build Coastguard Worker return result;
5108*38e8c45fSAndroid Build Coastguard Worker }
5109*38e8c45fSAndroid Build Coastguard Worker
setInjectionResult(const EventEntry & entry,InputEventInjectionResult injectionResult)5110*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::setInjectionResult(const EventEntry& entry,
5111*38e8c45fSAndroid Build Coastguard Worker InputEventInjectionResult injectionResult) {
5112*38e8c45fSAndroid Build Coastguard Worker if (!entry.injectionState) {
5113*38e8c45fSAndroid Build Coastguard Worker // Not an injected event.
5114*38e8c45fSAndroid Build Coastguard Worker return;
5115*38e8c45fSAndroid Build Coastguard Worker }
5116*38e8c45fSAndroid Build Coastguard Worker
5117*38e8c45fSAndroid Build Coastguard Worker InjectionState& injectionState = *entry.injectionState;
5118*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_INJECTION) {
5119*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "Setting input event injection result to "
5120*38e8c45fSAndroid Build Coastguard Worker << ftl::enum_string(injectionResult);
5121*38e8c45fSAndroid Build Coastguard Worker }
5122*38e8c45fSAndroid Build Coastguard Worker
5123*38e8c45fSAndroid Build Coastguard Worker if (injectionState.injectionIsAsync && !(entry.policyFlags & POLICY_FLAG_FILTERED)) {
5124*38e8c45fSAndroid Build Coastguard Worker // Log the outcome since the injector did not wait for the injection result.
5125*38e8c45fSAndroid Build Coastguard Worker switch (injectionResult) {
5126*38e8c45fSAndroid Build Coastguard Worker case InputEventInjectionResult::SUCCEEDED:
5127*38e8c45fSAndroid Build Coastguard Worker ALOGV("Asynchronous input event injection succeeded.");
5128*38e8c45fSAndroid Build Coastguard Worker break;
5129*38e8c45fSAndroid Build Coastguard Worker case InputEventInjectionResult::TARGET_MISMATCH:
5130*38e8c45fSAndroid Build Coastguard Worker ALOGV("Asynchronous input event injection target mismatch.");
5131*38e8c45fSAndroid Build Coastguard Worker break;
5132*38e8c45fSAndroid Build Coastguard Worker case InputEventInjectionResult::FAILED:
5133*38e8c45fSAndroid Build Coastguard Worker ALOGW("Asynchronous input event injection failed.");
5134*38e8c45fSAndroid Build Coastguard Worker break;
5135*38e8c45fSAndroid Build Coastguard Worker case InputEventInjectionResult::TIMED_OUT:
5136*38e8c45fSAndroid Build Coastguard Worker ALOGW("Asynchronous input event injection timed out.");
5137*38e8c45fSAndroid Build Coastguard Worker break;
5138*38e8c45fSAndroid Build Coastguard Worker case InputEventInjectionResult::PENDING:
5139*38e8c45fSAndroid Build Coastguard Worker ALOGE("Setting result to 'PENDING' for asynchronous injection");
5140*38e8c45fSAndroid Build Coastguard Worker break;
5141*38e8c45fSAndroid Build Coastguard Worker }
5142*38e8c45fSAndroid Build Coastguard Worker }
5143*38e8c45fSAndroid Build Coastguard Worker
5144*38e8c45fSAndroid Build Coastguard Worker injectionState.injectionResult = injectionResult;
5145*38e8c45fSAndroid Build Coastguard Worker mInjectionResultAvailable.notify_all();
5146*38e8c45fSAndroid Build Coastguard Worker }
5147*38e8c45fSAndroid Build Coastguard Worker
transformMotionEntryForInjectionLocked(MotionEntry & entry,const ui::Transform & injectedTransform) const5148*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::transformMotionEntryForInjectionLocked(
5149*38e8c45fSAndroid Build Coastguard Worker MotionEntry& entry, const ui::Transform& injectedTransform) const {
5150*38e8c45fSAndroid Build Coastguard Worker // Input injection works in the logical display coordinate space, but the input pipeline works
5151*38e8c45fSAndroid Build Coastguard Worker // display space, so we need to transform the injected events accordingly.
5152*38e8c45fSAndroid Build Coastguard Worker const auto it = mDisplayInfos.find(entry.displayId);
5153*38e8c45fSAndroid Build Coastguard Worker if (it == mDisplayInfos.end()) return;
5154*38e8c45fSAndroid Build Coastguard Worker const auto& transformToDisplay = it->second.transform.inverse() * injectedTransform;
5155*38e8c45fSAndroid Build Coastguard Worker
5156*38e8c45fSAndroid Build Coastguard Worker if (entry.xCursorPosition != AMOTION_EVENT_INVALID_CURSOR_POSITION &&
5157*38e8c45fSAndroid Build Coastguard Worker entry.yCursorPosition != AMOTION_EVENT_INVALID_CURSOR_POSITION) {
5158*38e8c45fSAndroid Build Coastguard Worker const vec2 cursor =
5159*38e8c45fSAndroid Build Coastguard Worker MotionEvent::calculateTransformedXY(entry.source, transformToDisplay,
5160*38e8c45fSAndroid Build Coastguard Worker {entry.xCursorPosition, entry.yCursorPosition});
5161*38e8c45fSAndroid Build Coastguard Worker entry.xCursorPosition = cursor.x;
5162*38e8c45fSAndroid Build Coastguard Worker entry.yCursorPosition = cursor.y;
5163*38e8c45fSAndroid Build Coastguard Worker }
5164*38e8c45fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < entry.getPointerCount(); i++) {
5165*38e8c45fSAndroid Build Coastguard Worker entry.pointerCoords[i] =
5166*38e8c45fSAndroid Build Coastguard Worker MotionEvent::calculateTransformedCoords(entry.source, entry.flags,
5167*38e8c45fSAndroid Build Coastguard Worker transformToDisplay, entry.pointerCoords[i]);
5168*38e8c45fSAndroid Build Coastguard Worker }
5169*38e8c45fSAndroid Build Coastguard Worker }
5170*38e8c45fSAndroid Build Coastguard Worker
incrementPendingForegroundDispatches(const EventEntry & entry)5171*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::incrementPendingForegroundDispatches(const EventEntry& entry) {
5172*38e8c45fSAndroid Build Coastguard Worker if (entry.injectionState) {
5173*38e8c45fSAndroid Build Coastguard Worker entry.injectionState->pendingForegroundDispatches += 1;
5174*38e8c45fSAndroid Build Coastguard Worker }
5175*38e8c45fSAndroid Build Coastguard Worker }
5176*38e8c45fSAndroid Build Coastguard Worker
decrementPendingForegroundDispatches(const EventEntry & entry)5177*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::decrementPendingForegroundDispatches(const EventEntry& entry) {
5178*38e8c45fSAndroid Build Coastguard Worker if (entry.injectionState) {
5179*38e8c45fSAndroid Build Coastguard Worker entry.injectionState->pendingForegroundDispatches -= 1;
5180*38e8c45fSAndroid Build Coastguard Worker
5181*38e8c45fSAndroid Build Coastguard Worker if (entry.injectionState->pendingForegroundDispatches == 0) {
5182*38e8c45fSAndroid Build Coastguard Worker mInjectionSyncFinished.notify_all();
5183*38e8c45fSAndroid Build Coastguard Worker }
5184*38e8c45fSAndroid Build Coastguard Worker }
5185*38e8c45fSAndroid Build Coastguard Worker }
5186*38e8c45fSAndroid Build Coastguard Worker
getWindowHandlesLocked(ui::LogicalDisplayId displayId) const5187*38e8c45fSAndroid Build Coastguard Worker const std::vector<sp<WindowInfoHandle>>& InputDispatcher::getWindowHandlesLocked(
5188*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId displayId) const {
5189*38e8c45fSAndroid Build Coastguard Worker static const std::vector<sp<WindowInfoHandle>> EMPTY_WINDOW_HANDLES;
5190*38e8c45fSAndroid Build Coastguard Worker auto it = mWindowHandlesByDisplay.find(displayId);
5191*38e8c45fSAndroid Build Coastguard Worker return it != mWindowHandlesByDisplay.end() ? it->second : EMPTY_WINDOW_HANDLES;
5192*38e8c45fSAndroid Build Coastguard Worker }
5193*38e8c45fSAndroid Build Coastguard Worker
getWindowHandleLocked(const sp<IBinder> & windowHandleToken,std::optional<ui::LogicalDisplayId> displayId) const5194*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> InputDispatcher::getWindowHandleLocked(
5195*38e8c45fSAndroid Build Coastguard Worker const sp<IBinder>& windowHandleToken, std::optional<ui::LogicalDisplayId> displayId) const {
5196*38e8c45fSAndroid Build Coastguard Worker if (windowHandleToken == nullptr) {
5197*38e8c45fSAndroid Build Coastguard Worker return nullptr;
5198*38e8c45fSAndroid Build Coastguard Worker }
5199*38e8c45fSAndroid Build Coastguard Worker
5200*38e8c45fSAndroid Build Coastguard Worker if (!displayId) {
5201*38e8c45fSAndroid Build Coastguard Worker // Look through all displays.
5202*38e8c45fSAndroid Build Coastguard Worker for (const auto& [_, windowHandles] : mWindowHandlesByDisplay) {
5203*38e8c45fSAndroid Build Coastguard Worker for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {
5204*38e8c45fSAndroid Build Coastguard Worker if (windowHandle->getToken() == windowHandleToken) {
5205*38e8c45fSAndroid Build Coastguard Worker return windowHandle;
5206*38e8c45fSAndroid Build Coastguard Worker }
5207*38e8c45fSAndroid Build Coastguard Worker }
5208*38e8c45fSAndroid Build Coastguard Worker }
5209*38e8c45fSAndroid Build Coastguard Worker return nullptr;
5210*38e8c45fSAndroid Build Coastguard Worker }
5211*38e8c45fSAndroid Build Coastguard Worker
5212*38e8c45fSAndroid Build Coastguard Worker // Only look through the requested display.
5213*38e8c45fSAndroid Build Coastguard Worker for (const sp<WindowInfoHandle>& windowHandle : getWindowHandlesLocked(*displayId)) {
5214*38e8c45fSAndroid Build Coastguard Worker if (windowHandle->getToken() == windowHandleToken) {
5215*38e8c45fSAndroid Build Coastguard Worker return windowHandle;
5216*38e8c45fSAndroid Build Coastguard Worker }
5217*38e8c45fSAndroid Build Coastguard Worker }
5218*38e8c45fSAndroid Build Coastguard Worker return nullptr;
5219*38e8c45fSAndroid Build Coastguard Worker }
5220*38e8c45fSAndroid Build Coastguard Worker
getWindowHandleLocked(const sp<WindowInfoHandle> & windowHandle) const5221*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> InputDispatcher::getWindowHandleLocked(
5222*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle>& windowHandle) const {
5223*38e8c45fSAndroid Build Coastguard Worker for (const auto& [displayId, windowHandles] : mWindowHandlesByDisplay) {
5224*38e8c45fSAndroid Build Coastguard Worker for (const sp<WindowInfoHandle>& handle : windowHandles) {
5225*38e8c45fSAndroid Build Coastguard Worker if (handle->getId() == windowHandle->getId() &&
5226*38e8c45fSAndroid Build Coastguard Worker handle->getToken() == windowHandle->getToken()) {
5227*38e8c45fSAndroid Build Coastguard Worker if (windowHandle->getInfo()->displayId != displayId) {
5228*38e8c45fSAndroid Build Coastguard Worker ALOGE("Found window %s in display %s"
5229*38e8c45fSAndroid Build Coastguard Worker ", but it should belong to display %s",
5230*38e8c45fSAndroid Build Coastguard Worker windowHandle->getName().c_str(), displayId.toString().c_str(),
5231*38e8c45fSAndroid Build Coastguard Worker windowHandle->getInfo()->displayId.toString().c_str());
5232*38e8c45fSAndroid Build Coastguard Worker }
5233*38e8c45fSAndroid Build Coastguard Worker return handle;
5234*38e8c45fSAndroid Build Coastguard Worker }
5235*38e8c45fSAndroid Build Coastguard Worker }
5236*38e8c45fSAndroid Build Coastguard Worker }
5237*38e8c45fSAndroid Build Coastguard Worker return nullptr;
5238*38e8c45fSAndroid Build Coastguard Worker }
5239*38e8c45fSAndroid Build Coastguard Worker
getFocusedWindowHandleLocked(ui::LogicalDisplayId displayId) const5240*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> InputDispatcher::getFocusedWindowHandleLocked(
5241*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId displayId) const {
5242*38e8c45fSAndroid Build Coastguard Worker sp<IBinder> focusedToken = mFocusResolver.getFocusedWindowToken(displayId);
5243*38e8c45fSAndroid Build Coastguard Worker return getWindowHandleLocked(focusedToken, displayId);
5244*38e8c45fSAndroid Build Coastguard Worker }
5245*38e8c45fSAndroid Build Coastguard Worker
getTransformLocked(ui::LogicalDisplayId displayId) const5246*38e8c45fSAndroid Build Coastguard Worker ui::Transform InputDispatcher::getTransformLocked(ui::LogicalDisplayId displayId) const {
5247*38e8c45fSAndroid Build Coastguard Worker auto displayInfoIt = mDisplayInfos.find(displayId);
5248*38e8c45fSAndroid Build Coastguard Worker return displayInfoIt != mDisplayInfos.end() ? displayInfoIt->second.transform
5249*38e8c45fSAndroid Build Coastguard Worker : kIdentityTransform;
5250*38e8c45fSAndroid Build Coastguard Worker }
5251*38e8c45fSAndroid Build Coastguard Worker
canWindowReceiveMotionLocked(const sp<WindowInfoHandle> & window,const MotionEntry & motionEntry) const5252*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::canWindowReceiveMotionLocked(const sp<WindowInfoHandle>& window,
5253*38e8c45fSAndroid Build Coastguard Worker const MotionEntry& motionEntry) const {
5254*38e8c45fSAndroid Build Coastguard Worker const WindowInfo& info = *window->getInfo();
5255*38e8c45fSAndroid Build Coastguard Worker
5256*38e8c45fSAndroid Build Coastguard Worker // Skip spy window targets that are not valid for targeted injection.
5257*38e8c45fSAndroid Build Coastguard Worker if (const auto err = verifyTargetedInjection(window, motionEntry); err) {
5258*38e8c45fSAndroid Build Coastguard Worker return false;
5259*38e8c45fSAndroid Build Coastguard Worker }
5260*38e8c45fSAndroid Build Coastguard Worker
5261*38e8c45fSAndroid Build Coastguard Worker if (info.inputConfig.test(WindowInfo::InputConfig::PAUSE_DISPATCHING)) {
5262*38e8c45fSAndroid Build Coastguard Worker ALOGI("Not sending touch event to %s because it is paused", window->getName().c_str());
5263*38e8c45fSAndroid Build Coastguard Worker return false;
5264*38e8c45fSAndroid Build Coastguard Worker }
5265*38e8c45fSAndroid Build Coastguard Worker
5266*38e8c45fSAndroid Build Coastguard Worker if (info.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
5267*38e8c45fSAndroid Build Coastguard Worker ALOGW("Not sending touch gesture to %s because it has config NO_INPUT_CHANNEL",
5268*38e8c45fSAndroid Build Coastguard Worker window->getName().c_str());
5269*38e8c45fSAndroid Build Coastguard Worker return false;
5270*38e8c45fSAndroid Build Coastguard Worker }
5271*38e8c45fSAndroid Build Coastguard Worker
5272*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<Connection> connection = getConnectionLocked(window->getToken());
5273*38e8c45fSAndroid Build Coastguard Worker if (connection == nullptr) {
5274*38e8c45fSAndroid Build Coastguard Worker ALOGW("Not sending touch to %s because there's no corresponding connection",
5275*38e8c45fSAndroid Build Coastguard Worker window->getName().c_str());
5276*38e8c45fSAndroid Build Coastguard Worker return false;
5277*38e8c45fSAndroid Build Coastguard Worker }
5278*38e8c45fSAndroid Build Coastguard Worker
5279*38e8c45fSAndroid Build Coastguard Worker if (!connection->responsive) {
5280*38e8c45fSAndroid Build Coastguard Worker ALOGW("Not sending touch to %s because it is not responsive", window->getName().c_str());
5281*38e8c45fSAndroid Build Coastguard Worker return false;
5282*38e8c45fSAndroid Build Coastguard Worker }
5283*38e8c45fSAndroid Build Coastguard Worker
5284*38e8c45fSAndroid Build Coastguard Worker // Drop events that can't be trusted due to occlusion
5285*38e8c45fSAndroid Build Coastguard Worker const auto [x, y] = resolveTouchedPosition(motionEntry);
5286*38e8c45fSAndroid Build Coastguard Worker TouchOcclusionInfo occlusionInfo = computeTouchOcclusionInfoLocked(window, x, y);
5287*38e8c45fSAndroid Build Coastguard Worker if (!isTouchTrustedLocked(occlusionInfo)) {
5288*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_TOUCH_OCCLUSION) {
5289*38e8c45fSAndroid Build Coastguard Worker ALOGD("Stack of obscuring windows during untrusted touch (%.1f, %.1f):", x, y);
5290*38e8c45fSAndroid Build Coastguard Worker for (const auto& log : occlusionInfo.debugInfo) {
5291*38e8c45fSAndroid Build Coastguard Worker ALOGD("%s", log.c_str());
5292*38e8c45fSAndroid Build Coastguard Worker }
5293*38e8c45fSAndroid Build Coastguard Worker }
5294*38e8c45fSAndroid Build Coastguard Worker ALOGW("Dropping untrusted touch event due to %s/%s", occlusionInfo.obscuringPackage.c_str(),
5295*38e8c45fSAndroid Build Coastguard Worker occlusionInfo.obscuringUid.toString().c_str());
5296*38e8c45fSAndroid Build Coastguard Worker return false;
5297*38e8c45fSAndroid Build Coastguard Worker }
5298*38e8c45fSAndroid Build Coastguard Worker
5299*38e8c45fSAndroid Build Coastguard Worker // Drop touch events if requested by input feature
5300*38e8c45fSAndroid Build Coastguard Worker if (shouldDropInput(motionEntry, window)) {
5301*38e8c45fSAndroid Build Coastguard Worker return false;
5302*38e8c45fSAndroid Build Coastguard Worker }
5303*38e8c45fSAndroid Build Coastguard Worker
5304*38e8c45fSAndroid Build Coastguard Worker // Ignore touches if stylus is down anywhere on screen
5305*38e8c45fSAndroid Build Coastguard Worker if (info.inputConfig.test(WindowInfo::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH) &&
5306*38e8c45fSAndroid Build Coastguard Worker isStylusActiveInDisplay(info.displayId, mTouchStatesByDisplay)) {
5307*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "Dropping touch from " << window->getName() << " because stylus is active";
5308*38e8c45fSAndroid Build Coastguard Worker return false;
5309*38e8c45fSAndroid Build Coastguard Worker }
5310*38e8c45fSAndroid Build Coastguard Worker
5311*38e8c45fSAndroid Build Coastguard Worker return true;
5312*38e8c45fSAndroid Build Coastguard Worker }
5313*38e8c45fSAndroid Build Coastguard Worker
updateWindowHandlesForDisplayLocked(const std::vector<sp<WindowInfoHandle>> & windowInfoHandles,ui::LogicalDisplayId displayId)5314*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::updateWindowHandlesForDisplayLocked(
5315*38e8c45fSAndroid Build Coastguard Worker const std::vector<sp<WindowInfoHandle>>& windowInfoHandles,
5316*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId displayId) {
5317*38e8c45fSAndroid Build Coastguard Worker if (windowInfoHandles.empty()) {
5318*38e8c45fSAndroid Build Coastguard Worker // Remove all handles on a display if there are no windows left.
5319*38e8c45fSAndroid Build Coastguard Worker mWindowHandlesByDisplay.erase(displayId);
5320*38e8c45fSAndroid Build Coastguard Worker return;
5321*38e8c45fSAndroid Build Coastguard Worker }
5322*38e8c45fSAndroid Build Coastguard Worker
5323*38e8c45fSAndroid Build Coastguard Worker // Since we compare the pointer of input window handles across window updates, we need
5324*38e8c45fSAndroid Build Coastguard Worker // to make sure the handle object for the same window stays unchanged across updates.
5325*38e8c45fSAndroid Build Coastguard Worker const std::vector<sp<WindowInfoHandle>>& oldHandles = getWindowHandlesLocked(displayId);
5326*38e8c45fSAndroid Build Coastguard Worker std::unordered_map<int32_t /*id*/, sp<WindowInfoHandle>> oldHandlesById;
5327*38e8c45fSAndroid Build Coastguard Worker for (const sp<WindowInfoHandle>& handle : oldHandles) {
5328*38e8c45fSAndroid Build Coastguard Worker oldHandlesById[handle->getId()] = handle;
5329*38e8c45fSAndroid Build Coastguard Worker }
5330*38e8c45fSAndroid Build Coastguard Worker
5331*38e8c45fSAndroid Build Coastguard Worker std::vector<sp<WindowInfoHandle>> newHandles;
5332*38e8c45fSAndroid Build Coastguard Worker for (const sp<WindowInfoHandle>& handle : windowInfoHandles) {
5333*38e8c45fSAndroid Build Coastguard Worker const WindowInfo* info = handle->getInfo();
5334*38e8c45fSAndroid Build Coastguard Worker if (getConnectionLocked(handle->getToken()) == nullptr) {
5335*38e8c45fSAndroid Build Coastguard Worker const bool noInputChannel =
5336*38e8c45fSAndroid Build Coastguard Worker info->inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL);
5337*38e8c45fSAndroid Build Coastguard Worker const bool canReceiveInput =
5338*38e8c45fSAndroid Build Coastguard Worker !info->inputConfig.test(WindowInfo::InputConfig::NOT_TOUCHABLE) ||
5339*38e8c45fSAndroid Build Coastguard Worker !info->inputConfig.test(WindowInfo::InputConfig::NOT_FOCUSABLE);
5340*38e8c45fSAndroid Build Coastguard Worker if (canReceiveInput && !noInputChannel) {
5341*38e8c45fSAndroid Build Coastguard Worker ALOGV("Window handle %s has no registered input channel",
5342*38e8c45fSAndroid Build Coastguard Worker handle->getName().c_str());
5343*38e8c45fSAndroid Build Coastguard Worker continue;
5344*38e8c45fSAndroid Build Coastguard Worker }
5345*38e8c45fSAndroid Build Coastguard Worker }
5346*38e8c45fSAndroid Build Coastguard Worker
5347*38e8c45fSAndroid Build Coastguard Worker if (info->displayId != displayId) {
5348*38e8c45fSAndroid Build Coastguard Worker ALOGE("Window %s updated by wrong display %s, should belong to display %s",
5349*38e8c45fSAndroid Build Coastguard Worker handle->getName().c_str(), displayId.toString().c_str(),
5350*38e8c45fSAndroid Build Coastguard Worker info->displayId.toString().c_str());
5351*38e8c45fSAndroid Build Coastguard Worker continue;
5352*38e8c45fSAndroid Build Coastguard Worker }
5353*38e8c45fSAndroid Build Coastguard Worker
5354*38e8c45fSAndroid Build Coastguard Worker if ((oldHandlesById.find(handle->getId()) != oldHandlesById.end()) &&
5355*38e8c45fSAndroid Build Coastguard Worker (oldHandlesById.at(handle->getId())->getToken() == handle->getToken())) {
5356*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle>& oldHandle = oldHandlesById.at(handle->getId());
5357*38e8c45fSAndroid Build Coastguard Worker oldHandle->updateFrom(handle);
5358*38e8c45fSAndroid Build Coastguard Worker newHandles.push_back(oldHandle);
5359*38e8c45fSAndroid Build Coastguard Worker } else {
5360*38e8c45fSAndroid Build Coastguard Worker newHandles.push_back(handle);
5361*38e8c45fSAndroid Build Coastguard Worker }
5362*38e8c45fSAndroid Build Coastguard Worker }
5363*38e8c45fSAndroid Build Coastguard Worker
5364*38e8c45fSAndroid Build Coastguard Worker // Insert or replace
5365*38e8c45fSAndroid Build Coastguard Worker mWindowHandlesByDisplay[displayId] = newHandles;
5366*38e8c45fSAndroid Build Coastguard Worker }
5367*38e8c45fSAndroid Build Coastguard Worker
5368*38e8c45fSAndroid Build Coastguard Worker /**
5369*38e8c45fSAndroid Build Coastguard Worker * Called from InputManagerService, update window handle list by displayId that can receive input.
5370*38e8c45fSAndroid Build Coastguard Worker * A window handle contains information about InputChannel, Touch Region, Types, Focused,...
5371*38e8c45fSAndroid Build Coastguard Worker * If set an empty list, remove all handles from the specific display.
5372*38e8c45fSAndroid Build Coastguard Worker * For focused handle, check if need to change and send a cancel event to previous one.
5373*38e8c45fSAndroid Build Coastguard Worker * For removed handle, check if need to send a cancel event if already in touch.
5374*38e8c45fSAndroid Build Coastguard Worker */
setInputWindowsLocked(const std::vector<sp<WindowInfoHandle>> & windowInfoHandles,ui::LogicalDisplayId displayId)5375*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::setInputWindowsLocked(
5376*38e8c45fSAndroid Build Coastguard Worker const std::vector<sp<WindowInfoHandle>>& windowInfoHandles,
5377*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId displayId) {
5378*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_FOCUS) {
5379*38e8c45fSAndroid Build Coastguard Worker std::string windowList;
5380*38e8c45fSAndroid Build Coastguard Worker for (const sp<WindowInfoHandle>& iwh : windowInfoHandles) {
5381*38e8c45fSAndroid Build Coastguard Worker windowList += iwh->getName() + " ";
5382*38e8c45fSAndroid Build Coastguard Worker }
5383*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "setInputWindows displayId=" << displayId << " " << windowList;
5384*38e8c45fSAndroid Build Coastguard Worker }
5385*38e8c45fSAndroid Build Coastguard Worker ScopedSyntheticEventTracer traceContext(mTracer);
5386*38e8c45fSAndroid Build Coastguard Worker
5387*38e8c45fSAndroid Build Coastguard Worker // Check preconditions for new input windows
5388*38e8c45fSAndroid Build Coastguard Worker for (const sp<WindowInfoHandle>& window : windowInfoHandles) {
5389*38e8c45fSAndroid Build Coastguard Worker const WindowInfo& info = *window->getInfo();
5390*38e8c45fSAndroid Build Coastguard Worker
5391*38e8c45fSAndroid Build Coastguard Worker // Ensure all tokens are null if the window has feature NO_INPUT_CHANNEL
5392*38e8c45fSAndroid Build Coastguard Worker const bool noInputWindow = info.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL);
5393*38e8c45fSAndroid Build Coastguard Worker if (noInputWindow && window->getToken() != nullptr) {
5394*38e8c45fSAndroid Build Coastguard Worker ALOGE("%s has feature NO_INPUT_WINDOW, but a non-null token. Clearing",
5395*38e8c45fSAndroid Build Coastguard Worker window->getName().c_str());
5396*38e8c45fSAndroid Build Coastguard Worker window->releaseChannel();
5397*38e8c45fSAndroid Build Coastguard Worker }
5398*38e8c45fSAndroid Build Coastguard Worker
5399*38e8c45fSAndroid Build Coastguard Worker // Ensure all spy windows are trusted overlays
5400*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(info.isSpy() &&
5401*38e8c45fSAndroid Build Coastguard Worker !info.inputConfig.test(
5402*38e8c45fSAndroid Build Coastguard Worker WindowInfo::InputConfig::TRUSTED_OVERLAY),
5403*38e8c45fSAndroid Build Coastguard Worker "%s has feature SPY, but is not a trusted overlay.",
5404*38e8c45fSAndroid Build Coastguard Worker window->getName().c_str());
5405*38e8c45fSAndroid Build Coastguard Worker
5406*38e8c45fSAndroid Build Coastguard Worker // Ensure all stylus interceptors are trusted overlays
5407*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(info.interceptsStylus() &&
5408*38e8c45fSAndroid Build Coastguard Worker !info.inputConfig.test(
5409*38e8c45fSAndroid Build Coastguard Worker WindowInfo::InputConfig::TRUSTED_OVERLAY),
5410*38e8c45fSAndroid Build Coastguard Worker "%s has feature INTERCEPTS_STYLUS, but is not a trusted overlay.",
5411*38e8c45fSAndroid Build Coastguard Worker window->getName().c_str());
5412*38e8c45fSAndroid Build Coastguard Worker }
5413*38e8c45fSAndroid Build Coastguard Worker
5414*38e8c45fSAndroid Build Coastguard Worker // Copy old handles for release if they are no longer present.
5415*38e8c45fSAndroid Build Coastguard Worker const std::vector<sp<WindowInfoHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);
5416*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle> removedFocusedWindowHandle = getFocusedWindowHandleLocked(displayId);
5417*38e8c45fSAndroid Build Coastguard Worker
5418*38e8c45fSAndroid Build Coastguard Worker updateWindowHandlesForDisplayLocked(windowInfoHandles, displayId);
5419*38e8c45fSAndroid Build Coastguard Worker
5420*38e8c45fSAndroid Build Coastguard Worker const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);
5421*38e8c45fSAndroid Build Coastguard Worker
5422*38e8c45fSAndroid Build Coastguard Worker std::optional<FocusResolver::FocusChanges> changes =
5423*38e8c45fSAndroid Build Coastguard Worker mFocusResolver.setInputWindows(displayId, windowHandles);
5424*38e8c45fSAndroid Build Coastguard Worker if (changes) {
5425*38e8c45fSAndroid Build Coastguard Worker onFocusChangedLocked(*changes, traceContext.getTracker(), removedFocusedWindowHandle);
5426*38e8c45fSAndroid Build Coastguard Worker }
5427*38e8c45fSAndroid Build Coastguard Worker
5428*38e8c45fSAndroid Build Coastguard Worker if (const auto& it = mTouchStatesByDisplay.find(displayId); it != mTouchStatesByDisplay.end()) {
5429*38e8c45fSAndroid Build Coastguard Worker TouchState& state = it->second;
5430*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < state.windows.size();) {
5431*38e8c45fSAndroid Build Coastguard Worker TouchedWindow& touchedWindow = state.windows[i];
5432*38e8c45fSAndroid Build Coastguard Worker if (getWindowHandleLocked(touchedWindow.windowHandle) != nullptr) {
5433*38e8c45fSAndroid Build Coastguard Worker i++;
5434*38e8c45fSAndroid Build Coastguard Worker continue;
5435*38e8c45fSAndroid Build Coastguard Worker }
5436*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "Touched window was removed: " << touchedWindow.windowHandle->getName()
5437*38e8c45fSAndroid Build Coastguard Worker << " in display %" << displayId;
5438*38e8c45fSAndroid Build Coastguard Worker CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
5439*38e8c45fSAndroid Build Coastguard Worker "touched window was removed", traceContext.getTracker());
5440*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForWindowLocked(touchedWindow.windowHandle, options);
5441*38e8c45fSAndroid Build Coastguard Worker // Since we are about to drop the touch, cancel the events for the wallpaper as
5442*38e8c45fSAndroid Build Coastguard Worker // well.
5443*38e8c45fSAndroid Build Coastguard Worker if (touchedWindow.targetFlags.test(InputTarget::Flags::FOREGROUND) &&
5444*38e8c45fSAndroid Build Coastguard Worker touchedWindow.windowHandle->getInfo()->inputConfig.test(
5445*38e8c45fSAndroid Build Coastguard Worker gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
5446*38e8c45fSAndroid Build Coastguard Worker for (const DeviceId deviceId : touchedWindow.getTouchingDeviceIds()) {
5447*38e8c45fSAndroid Build Coastguard Worker if (const auto& ww = state.getWallpaperWindow(deviceId); ww != nullptr) {
5448*38e8c45fSAndroid Build Coastguard Worker options.deviceId = deviceId;
5449*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForWindowLocked(ww, options);
5450*38e8c45fSAndroid Build Coastguard Worker }
5451*38e8c45fSAndroid Build Coastguard Worker }
5452*38e8c45fSAndroid Build Coastguard Worker }
5453*38e8c45fSAndroid Build Coastguard Worker state.windows.erase(state.windows.begin() + i);
5454*38e8c45fSAndroid Build Coastguard Worker }
5455*38e8c45fSAndroid Build Coastguard Worker
5456*38e8c45fSAndroid Build Coastguard Worker // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We
5457*38e8c45fSAndroid Build Coastguard Worker // could just clear the state here.
5458*38e8c45fSAndroid Build Coastguard Worker if (mDragState && mDragState->dragWindow->getInfo()->displayId == displayId &&
5459*38e8c45fSAndroid Build Coastguard Worker std::find(windowHandles.begin(), windowHandles.end(), mDragState->dragWindow) ==
5460*38e8c45fSAndroid Build Coastguard Worker windowHandles.end()) {
5461*38e8c45fSAndroid Build Coastguard Worker ALOGI("Drag window went away: %s", mDragState->dragWindow->getName().c_str());
5462*38e8c45fSAndroid Build Coastguard Worker sendDropWindowCommandLocked(nullptr, 0, 0);
5463*38e8c45fSAndroid Build Coastguard Worker mDragState.reset();
5464*38e8c45fSAndroid Build Coastguard Worker }
5465*38e8c45fSAndroid Build Coastguard Worker }
5466*38e8c45fSAndroid Build Coastguard Worker
5467*38e8c45fSAndroid Build Coastguard Worker // Check if the hovering should stop because the window is no longer eligible to receive it
5468*38e8c45fSAndroid Build Coastguard Worker // (for example, if the touchable region changed)
5469*38e8c45fSAndroid Build Coastguard Worker if (const auto& it = mTouchStatesByDisplay.find(displayId); it != mTouchStatesByDisplay.end()) {
5470*38e8c45fSAndroid Build Coastguard Worker TouchState& state = it->second;
5471*38e8c45fSAndroid Build Coastguard Worker for (TouchedWindow& touchedWindow : state.windows) {
5472*38e8c45fSAndroid Build Coastguard Worker std::vector<DeviceId> erasedDevices = touchedWindow.eraseHoveringPointersIf(
5473*38e8c45fSAndroid Build Coastguard Worker [this, displayId, &touchedWindow](const PointerProperties& properties, float x,
5474*38e8c45fSAndroid Build Coastguard Worker float y) REQUIRES(mLock) {
5475*38e8c45fSAndroid Build Coastguard Worker const bool isStylus = properties.toolType == ToolType::STYLUS;
5476*38e8c45fSAndroid Build Coastguard Worker const ui::Transform displayTransform = getTransformLocked(displayId);
5477*38e8c45fSAndroid Build Coastguard Worker const bool stillAcceptsTouch =
5478*38e8c45fSAndroid Build Coastguard Worker windowAcceptsTouchAt(*touchedWindow.windowHandle->getInfo(),
5479*38e8c45fSAndroid Build Coastguard Worker displayId, x, y, isStylus, displayTransform);
5480*38e8c45fSAndroid Build Coastguard Worker return !stillAcceptsTouch;
5481*38e8c45fSAndroid Build Coastguard Worker });
5482*38e8c45fSAndroid Build Coastguard Worker
5483*38e8c45fSAndroid Build Coastguard Worker for (DeviceId deviceId : erasedDevices) {
5484*38e8c45fSAndroid Build Coastguard Worker CancelationOptions options(CancelationOptions::Mode::CANCEL_HOVER_EVENTS,
5485*38e8c45fSAndroid Build Coastguard Worker "WindowInfo changed",
5486*38e8c45fSAndroid Build Coastguard Worker traceContext.getTracker());
5487*38e8c45fSAndroid Build Coastguard Worker options.deviceId = deviceId;
5488*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForWindowLocked(touchedWindow.windowHandle, options);
5489*38e8c45fSAndroid Build Coastguard Worker }
5490*38e8c45fSAndroid Build Coastguard Worker }
5491*38e8c45fSAndroid Build Coastguard Worker }
5492*38e8c45fSAndroid Build Coastguard Worker
5493*38e8c45fSAndroid Build Coastguard Worker // Release information for windows that are no longer present.
5494*38e8c45fSAndroid Build Coastguard Worker // This ensures that unused input channels are released promptly.
5495*38e8c45fSAndroid Build Coastguard Worker // Otherwise, they might stick around until the window handle is destroyed
5496*38e8c45fSAndroid Build Coastguard Worker // which might not happen until the next GC.
5497*38e8c45fSAndroid Build Coastguard Worker for (const sp<WindowInfoHandle>& oldWindowHandle : oldWindowHandles) {
5498*38e8c45fSAndroid Build Coastguard Worker if (getWindowHandleLocked(oldWindowHandle) == nullptr) {
5499*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_FOCUS) {
5500*38e8c45fSAndroid Build Coastguard Worker ALOGD("Window went away: %s", oldWindowHandle->getName().c_str());
5501*38e8c45fSAndroid Build Coastguard Worker }
5502*38e8c45fSAndroid Build Coastguard Worker oldWindowHandle->releaseChannel();
5503*38e8c45fSAndroid Build Coastguard Worker }
5504*38e8c45fSAndroid Build Coastguard Worker }
5505*38e8c45fSAndroid Build Coastguard Worker }
5506*38e8c45fSAndroid Build Coastguard Worker
setFocusedApplication(ui::LogicalDisplayId displayId,const std::shared_ptr<InputApplicationHandle> & inputApplicationHandle)5507*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::setFocusedApplication(
5508*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId displayId,
5509*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) {
5510*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_FOCUS) {
5511*38e8c45fSAndroid Build Coastguard Worker ALOGD("setFocusedApplication displayId=%s %s", displayId.toString().c_str(),
5512*38e8c45fSAndroid Build Coastguard Worker inputApplicationHandle ? inputApplicationHandle->getName().c_str() : "<nullptr>");
5513*38e8c45fSAndroid Build Coastguard Worker }
5514*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
5515*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
5516*38e8c45fSAndroid Build Coastguard Worker setFocusedApplicationLocked(displayId, inputApplicationHandle);
5517*38e8c45fSAndroid Build Coastguard Worker } // release lock
5518*38e8c45fSAndroid Build Coastguard Worker
5519*38e8c45fSAndroid Build Coastguard Worker // Wake up poll loop since it may need to make new input dispatching choices.
5520*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
5521*38e8c45fSAndroid Build Coastguard Worker }
5522*38e8c45fSAndroid Build Coastguard Worker
setFocusedApplicationLocked(ui::LogicalDisplayId displayId,const std::shared_ptr<InputApplicationHandle> & inputApplicationHandle)5523*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::setFocusedApplicationLocked(
5524*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId displayId,
5525*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) {
5526*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<InputApplicationHandle> oldFocusedApplicationHandle =
5527*38e8c45fSAndroid Build Coastguard Worker getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
5528*38e8c45fSAndroid Build Coastguard Worker
5529*38e8c45fSAndroid Build Coastguard Worker if (sharedPointersEqual(oldFocusedApplicationHandle, inputApplicationHandle)) {
5530*38e8c45fSAndroid Build Coastguard Worker return; // This application is already focused. No need to wake up or change anything.
5531*38e8c45fSAndroid Build Coastguard Worker }
5532*38e8c45fSAndroid Build Coastguard Worker
5533*38e8c45fSAndroid Build Coastguard Worker // Set the new application handle.
5534*38e8c45fSAndroid Build Coastguard Worker if (inputApplicationHandle != nullptr) {
5535*38e8c45fSAndroid Build Coastguard Worker mFocusedApplicationHandlesByDisplay[displayId] = inputApplicationHandle;
5536*38e8c45fSAndroid Build Coastguard Worker } else {
5537*38e8c45fSAndroid Build Coastguard Worker mFocusedApplicationHandlesByDisplay.erase(displayId);
5538*38e8c45fSAndroid Build Coastguard Worker }
5539*38e8c45fSAndroid Build Coastguard Worker
5540*38e8c45fSAndroid Build Coastguard Worker // No matter what the old focused application was, stop waiting on it because it is
5541*38e8c45fSAndroid Build Coastguard Worker // no longer focused.
5542*38e8c45fSAndroid Build Coastguard Worker resetNoFocusedWindowTimeoutLocked();
5543*38e8c45fSAndroid Build Coastguard Worker }
5544*38e8c45fSAndroid Build Coastguard Worker
setMinTimeBetweenUserActivityPokes(std::chrono::milliseconds interval)5545*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::setMinTimeBetweenUserActivityPokes(std::chrono::milliseconds interval) {
5546*38e8c45fSAndroid Build Coastguard Worker if (interval.count() < 0) {
5547*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("Minimum time between user activity pokes should be >= 0");
5548*38e8c45fSAndroid Build Coastguard Worker }
5549*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
5550*38e8c45fSAndroid Build Coastguard Worker mMinTimeBetweenUserActivityPokes = interval;
5551*38e8c45fSAndroid Build Coastguard Worker }
5552*38e8c45fSAndroid Build Coastguard Worker
5553*38e8c45fSAndroid Build Coastguard Worker /**
5554*38e8c45fSAndroid Build Coastguard Worker * Sets the focused display, which is responsible for receiving focus-dispatched input events where
5555*38e8c45fSAndroid Build Coastguard Worker * the display not specified.
5556*38e8c45fSAndroid Build Coastguard Worker *
5557*38e8c45fSAndroid Build Coastguard Worker * We track any unreleased events for each window. If a window loses the ability to receive the
5558*38e8c45fSAndroid Build Coastguard Worker * released event, we will send a cancel event to it. So when the focused display is changed, we
5559*38e8c45fSAndroid Build Coastguard Worker * cancel all the unreleased display-unspecified events for the focused window on the old focused
5560*38e8c45fSAndroid Build Coastguard Worker * display. The display-specified events won't be affected.
5561*38e8c45fSAndroid Build Coastguard Worker */
setFocusedDisplay(ui::LogicalDisplayId displayId)5562*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::setFocusedDisplay(ui::LogicalDisplayId displayId) {
5563*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_FOCUS) {
5564*38e8c45fSAndroid Build Coastguard Worker ALOGD("setFocusedDisplay displayId=%s", displayId.toString().c_str());
5565*38e8c45fSAndroid Build Coastguard Worker }
5566*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
5567*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
5568*38e8c45fSAndroid Build Coastguard Worker ScopedSyntheticEventTracer traceContext(mTracer);
5569*38e8c45fSAndroid Build Coastguard Worker
5570*38e8c45fSAndroid Build Coastguard Worker if (mFocusedDisplayId != displayId) {
5571*38e8c45fSAndroid Build Coastguard Worker sp<IBinder> oldFocusedWindowToken =
5572*38e8c45fSAndroid Build Coastguard Worker mFocusResolver.getFocusedWindowToken(mFocusedDisplayId);
5573*38e8c45fSAndroid Build Coastguard Worker if (oldFocusedWindowToken != nullptr) {
5574*38e8c45fSAndroid Build Coastguard Worker const auto windowHandle =
5575*38e8c45fSAndroid Build Coastguard Worker getWindowHandleLocked(oldFocusedWindowToken, mFocusedDisplayId);
5576*38e8c45fSAndroid Build Coastguard Worker if (windowHandle == nullptr) {
5577*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << __func__ << ": Previously focused token did not have a window";
5578*38e8c45fSAndroid Build Coastguard Worker }
5579*38e8c45fSAndroid Build Coastguard Worker CancelationOptions
5580*38e8c45fSAndroid Build Coastguard Worker options(CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS,
5581*38e8c45fSAndroid Build Coastguard Worker "The display which contains this window no longer has focus.",
5582*38e8c45fSAndroid Build Coastguard Worker traceContext.getTracker());
5583*38e8c45fSAndroid Build Coastguard Worker options.displayId = ui::LogicalDisplayId::INVALID;
5584*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForWindowLocked(windowHandle, options);
5585*38e8c45fSAndroid Build Coastguard Worker }
5586*38e8c45fSAndroid Build Coastguard Worker mFocusedDisplayId = displayId;
5587*38e8c45fSAndroid Build Coastguard Worker // Enqueue a command to run outside the lock to tell the policy that the focused display
5588*38e8c45fSAndroid Build Coastguard Worker // changed.
5589*38e8c45fSAndroid Build Coastguard Worker auto command = [this]() REQUIRES(mLock) {
5590*38e8c45fSAndroid Build Coastguard Worker scoped_unlock unlock(mLock);
5591*38e8c45fSAndroid Build Coastguard Worker mPolicy.notifyFocusedDisplayChanged(mFocusedDisplayId);
5592*38e8c45fSAndroid Build Coastguard Worker };
5593*38e8c45fSAndroid Build Coastguard Worker postCommandLocked(std::move(command));
5594*38e8c45fSAndroid Build Coastguard Worker
5595*38e8c45fSAndroid Build Coastguard Worker // Only a window on the focused display can have Pointer Capture, so disable the active
5596*38e8c45fSAndroid Build Coastguard Worker // Pointer Capture session if there is one, since the focused display changed.
5597*38e8c45fSAndroid Build Coastguard Worker disablePointerCaptureForcedLocked();
5598*38e8c45fSAndroid Build Coastguard Worker
5599*38e8c45fSAndroid Build Coastguard Worker // Find new focused window and validate
5600*38e8c45fSAndroid Build Coastguard Worker sp<IBinder> newFocusedWindowToken = mFocusResolver.getFocusedWindowToken(displayId);
5601*38e8c45fSAndroid Build Coastguard Worker sendFocusChangedCommandLocked(oldFocusedWindowToken, newFocusedWindowToken);
5602*38e8c45fSAndroid Build Coastguard Worker
5603*38e8c45fSAndroid Build Coastguard Worker if (newFocusedWindowToken == nullptr) {
5604*38e8c45fSAndroid Build Coastguard Worker ALOGW("Focused display #%s does not have a focused window.",
5605*38e8c45fSAndroid Build Coastguard Worker displayId.toString().c_str());
5606*38e8c45fSAndroid Build Coastguard Worker if (mFocusResolver.hasFocusedWindowTokens()) {
5607*38e8c45fSAndroid Build Coastguard Worker ALOGE("But another display has a focused window\n%s",
5608*38e8c45fSAndroid Build Coastguard Worker mFocusResolver.dumpFocusedWindows().c_str());
5609*38e8c45fSAndroid Build Coastguard Worker }
5610*38e8c45fSAndroid Build Coastguard Worker }
5611*38e8c45fSAndroid Build Coastguard Worker }
5612*38e8c45fSAndroid Build Coastguard Worker } // release lock
5613*38e8c45fSAndroid Build Coastguard Worker
5614*38e8c45fSAndroid Build Coastguard Worker // Wake up poll loop since it may need to make new input dispatching choices.
5615*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
5616*38e8c45fSAndroid Build Coastguard Worker }
5617*38e8c45fSAndroid Build Coastguard Worker
setInputDispatchMode(bool enabled,bool frozen)5618*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
5619*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_FOCUS) {
5620*38e8c45fSAndroid Build Coastguard Worker ALOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
5621*38e8c45fSAndroid Build Coastguard Worker }
5622*38e8c45fSAndroid Build Coastguard Worker
5623*38e8c45fSAndroid Build Coastguard Worker bool changed;
5624*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
5625*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
5626*38e8c45fSAndroid Build Coastguard Worker
5627*38e8c45fSAndroid Build Coastguard Worker if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
5628*38e8c45fSAndroid Build Coastguard Worker if (mDispatchFrozen && !frozen) {
5629*38e8c45fSAndroid Build Coastguard Worker resetNoFocusedWindowTimeoutLocked();
5630*38e8c45fSAndroid Build Coastguard Worker }
5631*38e8c45fSAndroid Build Coastguard Worker
5632*38e8c45fSAndroid Build Coastguard Worker if (mDispatchEnabled && !enabled) {
5633*38e8c45fSAndroid Build Coastguard Worker resetAndDropEverythingLocked("dispatcher is being disabled");
5634*38e8c45fSAndroid Build Coastguard Worker }
5635*38e8c45fSAndroid Build Coastguard Worker
5636*38e8c45fSAndroid Build Coastguard Worker mDispatchEnabled = enabled;
5637*38e8c45fSAndroid Build Coastguard Worker mDispatchFrozen = frozen;
5638*38e8c45fSAndroid Build Coastguard Worker changed = true;
5639*38e8c45fSAndroid Build Coastguard Worker } else {
5640*38e8c45fSAndroid Build Coastguard Worker changed = false;
5641*38e8c45fSAndroid Build Coastguard Worker }
5642*38e8c45fSAndroid Build Coastguard Worker } // release lock
5643*38e8c45fSAndroid Build Coastguard Worker
5644*38e8c45fSAndroid Build Coastguard Worker if (changed) {
5645*38e8c45fSAndroid Build Coastguard Worker // Wake up poll loop since it may need to make new input dispatching choices.
5646*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
5647*38e8c45fSAndroid Build Coastguard Worker }
5648*38e8c45fSAndroid Build Coastguard Worker }
5649*38e8c45fSAndroid Build Coastguard Worker
setInputFilterEnabled(bool enabled)5650*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::setInputFilterEnabled(bool enabled) {
5651*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_FOCUS) {
5652*38e8c45fSAndroid Build Coastguard Worker ALOGD("setInputFilterEnabled: enabled=%d", enabled);
5653*38e8c45fSAndroid Build Coastguard Worker }
5654*38e8c45fSAndroid Build Coastguard Worker
5655*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
5656*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
5657*38e8c45fSAndroid Build Coastguard Worker
5658*38e8c45fSAndroid Build Coastguard Worker if (mInputFilterEnabled == enabled) {
5659*38e8c45fSAndroid Build Coastguard Worker return;
5660*38e8c45fSAndroid Build Coastguard Worker }
5661*38e8c45fSAndroid Build Coastguard Worker
5662*38e8c45fSAndroid Build Coastguard Worker mInputFilterEnabled = enabled;
5663*38e8c45fSAndroid Build Coastguard Worker resetAndDropEverythingLocked("input filter is being enabled or disabled");
5664*38e8c45fSAndroid Build Coastguard Worker } // release lock
5665*38e8c45fSAndroid Build Coastguard Worker
5666*38e8c45fSAndroid Build Coastguard Worker // Wake up poll loop since there might be work to do to drop everything.
5667*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
5668*38e8c45fSAndroid Build Coastguard Worker }
5669*38e8c45fSAndroid Build Coastguard Worker
setInTouchMode(bool inTouchMode,gui::Pid pid,gui::Uid uid,bool hasPermission,ui::LogicalDisplayId displayId)5670*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::setInTouchMode(bool inTouchMode, gui::Pid pid, gui::Uid uid,
5671*38e8c45fSAndroid Build Coastguard Worker bool hasPermission, ui::LogicalDisplayId displayId) {
5672*38e8c45fSAndroid Build Coastguard Worker bool needWake = false;
5673*38e8c45fSAndroid Build Coastguard Worker {
5674*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mLock);
5675*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(DEBUG_TOUCH_MODE,
5676*38e8c45fSAndroid Build Coastguard Worker "Request to change touch mode to %s (calling pid=%s, uid=%s, "
5677*38e8c45fSAndroid Build Coastguard Worker "hasPermission=%s, target displayId=%s, mTouchModePerDisplay[displayId]=%s)",
5678*38e8c45fSAndroid Build Coastguard Worker toString(inTouchMode), pid.toString().c_str(), uid.toString().c_str(),
5679*38e8c45fSAndroid Build Coastguard Worker toString(hasPermission), displayId.toString().c_str(),
5680*38e8c45fSAndroid Build Coastguard Worker mTouchModePerDisplay.count(displayId) == 0
5681*38e8c45fSAndroid Build Coastguard Worker ? "not set"
5682*38e8c45fSAndroid Build Coastguard Worker : std::to_string(mTouchModePerDisplay[displayId]).c_str());
5683*38e8c45fSAndroid Build Coastguard Worker
5684*38e8c45fSAndroid Build Coastguard Worker auto touchModeIt = mTouchModePerDisplay.find(displayId);
5685*38e8c45fSAndroid Build Coastguard Worker if (touchModeIt != mTouchModePerDisplay.end() && touchModeIt->second == inTouchMode) {
5686*38e8c45fSAndroid Build Coastguard Worker return false;
5687*38e8c45fSAndroid Build Coastguard Worker }
5688*38e8c45fSAndroid Build Coastguard Worker if (!hasPermission) {
5689*38e8c45fSAndroid Build Coastguard Worker if (!focusedWindowIsOwnedByLocked(pid, uid) &&
5690*38e8c45fSAndroid Build Coastguard Worker !recentWindowsAreOwnedByLocked(pid, uid)) {
5691*38e8c45fSAndroid Build Coastguard Worker ALOGD("Touch mode switch rejected, caller (pid=%s, uid=%s) doesn't own the focused "
5692*38e8c45fSAndroid Build Coastguard Worker "window nor none of the previously interacted window",
5693*38e8c45fSAndroid Build Coastguard Worker pid.toString().c_str(), uid.toString().c_str());
5694*38e8c45fSAndroid Build Coastguard Worker return false;
5695*38e8c45fSAndroid Build Coastguard Worker }
5696*38e8c45fSAndroid Build Coastguard Worker }
5697*38e8c45fSAndroid Build Coastguard Worker mTouchModePerDisplay[displayId] = inTouchMode;
5698*38e8c45fSAndroid Build Coastguard Worker auto entry = std::make_unique<TouchModeEntry>(mIdGenerator.nextId(), now(), inTouchMode,
5699*38e8c45fSAndroid Build Coastguard Worker displayId);
5700*38e8c45fSAndroid Build Coastguard Worker needWake = enqueueInboundEventLocked(std::move(entry));
5701*38e8c45fSAndroid Build Coastguard Worker } // release lock
5702*38e8c45fSAndroid Build Coastguard Worker
5703*38e8c45fSAndroid Build Coastguard Worker if (needWake) {
5704*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
5705*38e8c45fSAndroid Build Coastguard Worker }
5706*38e8c45fSAndroid Build Coastguard Worker return true;
5707*38e8c45fSAndroid Build Coastguard Worker }
5708*38e8c45fSAndroid Build Coastguard Worker
focusedWindowIsOwnedByLocked(gui::Pid pid,gui::Uid uid)5709*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::focusedWindowIsOwnedByLocked(gui::Pid pid, gui::Uid uid) {
5710*38e8c45fSAndroid Build Coastguard Worker const sp<IBinder> focusedToken = mFocusResolver.getFocusedWindowToken(mFocusedDisplayId);
5711*38e8c45fSAndroid Build Coastguard Worker if (focusedToken == nullptr) {
5712*38e8c45fSAndroid Build Coastguard Worker return false;
5713*38e8c45fSAndroid Build Coastguard Worker }
5714*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> windowHandle = getWindowHandleLocked(focusedToken);
5715*38e8c45fSAndroid Build Coastguard Worker return isWindowOwnedBy(windowHandle, pid, uid);
5716*38e8c45fSAndroid Build Coastguard Worker }
5717*38e8c45fSAndroid Build Coastguard Worker
recentWindowsAreOwnedByLocked(gui::Pid pid,gui::Uid uid)5718*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::recentWindowsAreOwnedByLocked(gui::Pid pid, gui::Uid uid) {
5719*38e8c45fSAndroid Build Coastguard Worker return std::find_if(mInteractionConnectionTokens.begin(), mInteractionConnectionTokens.end(),
5720*38e8c45fSAndroid Build Coastguard Worker [&](const sp<IBinder>& connectionToken) REQUIRES(mLock) {
5721*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle> windowHandle =
5722*38e8c45fSAndroid Build Coastguard Worker getWindowHandleLocked(connectionToken);
5723*38e8c45fSAndroid Build Coastguard Worker return isWindowOwnedBy(windowHandle, pid, uid);
5724*38e8c45fSAndroid Build Coastguard Worker }) != mInteractionConnectionTokens.end();
5725*38e8c45fSAndroid Build Coastguard Worker }
5726*38e8c45fSAndroid Build Coastguard Worker
setMaximumObscuringOpacityForTouch(float opacity)5727*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::setMaximumObscuringOpacityForTouch(float opacity) {
5728*38e8c45fSAndroid Build Coastguard Worker if (opacity < 0 || opacity > 1) {
5729*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("Maximum obscuring opacity for touch should be >= 0 and <= 1");
5730*38e8c45fSAndroid Build Coastguard Worker return;
5731*38e8c45fSAndroid Build Coastguard Worker }
5732*38e8c45fSAndroid Build Coastguard Worker
5733*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mLock);
5734*38e8c45fSAndroid Build Coastguard Worker mMaximumObscuringOpacityForTouch = opacity;
5735*38e8c45fSAndroid Build Coastguard Worker }
5736*38e8c45fSAndroid Build Coastguard Worker
5737*38e8c45fSAndroid Build Coastguard Worker std::tuple<TouchState*, TouchedWindow*, ui::LogicalDisplayId>
findTouchStateWindowAndDisplayLocked(const sp<IBinder> & token)5738*38e8c45fSAndroid Build Coastguard Worker InputDispatcher::findTouchStateWindowAndDisplayLocked(const sp<IBinder>& token) {
5739*38e8c45fSAndroid Build Coastguard Worker for (auto& [displayId, state] : mTouchStatesByDisplay) {
5740*38e8c45fSAndroid Build Coastguard Worker for (TouchedWindow& w : state.windows) {
5741*38e8c45fSAndroid Build Coastguard Worker if (w.windowHandle->getToken() == token) {
5742*38e8c45fSAndroid Build Coastguard Worker return std::make_tuple(&state, &w, displayId);
5743*38e8c45fSAndroid Build Coastguard Worker }
5744*38e8c45fSAndroid Build Coastguard Worker }
5745*38e8c45fSAndroid Build Coastguard Worker }
5746*38e8c45fSAndroid Build Coastguard Worker return std::make_tuple(nullptr, nullptr, ui::LogicalDisplayId::DEFAULT);
5747*38e8c45fSAndroid Build Coastguard Worker }
5748*38e8c45fSAndroid Build Coastguard Worker
5749*38e8c45fSAndroid Build Coastguard Worker std::tuple<const TouchState*, const TouchedWindow*, ui::LogicalDisplayId>
findTouchStateWindowAndDisplayLocked(const sp<IBinder> & token) const5750*38e8c45fSAndroid Build Coastguard Worker InputDispatcher::findTouchStateWindowAndDisplayLocked(const sp<IBinder>& token) const {
5751*38e8c45fSAndroid Build Coastguard Worker return const_cast<InputDispatcher*>(this)->findTouchStateWindowAndDisplayLocked(token);
5752*38e8c45fSAndroid Build Coastguard Worker }
5753*38e8c45fSAndroid Build Coastguard Worker
windowHasTouchingPointersLocked(const sp<WindowInfoHandle> & windowHandle,DeviceId deviceId) const5754*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::windowHasTouchingPointersLocked(const sp<WindowInfoHandle>& windowHandle,
5755*38e8c45fSAndroid Build Coastguard Worker DeviceId deviceId) const {
5756*38e8c45fSAndroid Build Coastguard Worker const auto& [touchState, touchedWindow, _] =
5757*38e8c45fSAndroid Build Coastguard Worker findTouchStateWindowAndDisplayLocked(windowHandle->getToken());
5758*38e8c45fSAndroid Build Coastguard Worker if (touchState == nullptr) {
5759*38e8c45fSAndroid Build Coastguard Worker // No touching pointers at all
5760*38e8c45fSAndroid Build Coastguard Worker return false;
5761*38e8c45fSAndroid Build Coastguard Worker }
5762*38e8c45fSAndroid Build Coastguard Worker return touchState->hasTouchingPointers(deviceId);
5763*38e8c45fSAndroid Build Coastguard Worker }
5764*38e8c45fSAndroid Build Coastguard Worker
transferTouchGesture(const sp<IBinder> & fromToken,const sp<IBinder> & toToken,bool isDragDrop)5765*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::transferTouchGesture(const sp<IBinder>& fromToken, const sp<IBinder>& toToken,
5766*38e8c45fSAndroid Build Coastguard Worker bool isDragDrop) {
5767*38e8c45fSAndroid Build Coastguard Worker if (fromToken == toToken) {
5768*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_FOCUS) {
5769*38e8c45fSAndroid Build Coastguard Worker ALOGD("Trivial transfer to same window.");
5770*38e8c45fSAndroid Build Coastguard Worker }
5771*38e8c45fSAndroid Build Coastguard Worker return true;
5772*38e8c45fSAndroid Build Coastguard Worker }
5773*38e8c45fSAndroid Build Coastguard Worker
5774*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
5775*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
5776*38e8c45fSAndroid Build Coastguard Worker
5777*38e8c45fSAndroid Build Coastguard Worker // Find the target touch state and touched window by fromToken.
5778*38e8c45fSAndroid Build Coastguard Worker auto [state, touchedWindow, displayId] = findTouchStateWindowAndDisplayLocked(fromToken);
5779*38e8c45fSAndroid Build Coastguard Worker
5780*38e8c45fSAndroid Build Coastguard Worker if (state == nullptr || touchedWindow == nullptr) {
5781*38e8c45fSAndroid Build Coastguard Worker ALOGD("Touch transfer failed because from window is not being touched.");
5782*38e8c45fSAndroid Build Coastguard Worker return false;
5783*38e8c45fSAndroid Build Coastguard Worker }
5784*38e8c45fSAndroid Build Coastguard Worker std::set<DeviceId> deviceIds = touchedWindow->getTouchingDeviceIds();
5785*38e8c45fSAndroid Build Coastguard Worker if (deviceIds.size() != 1) {
5786*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "Can't transfer touch. Currently touching devices: " << dumpSet(deviceIds)
5787*38e8c45fSAndroid Build Coastguard Worker << " for window: " << touchedWindow->dump();
5788*38e8c45fSAndroid Build Coastguard Worker return false;
5789*38e8c45fSAndroid Build Coastguard Worker }
5790*38e8c45fSAndroid Build Coastguard Worker const DeviceId deviceId = *deviceIds.begin();
5791*38e8c45fSAndroid Build Coastguard Worker
5792*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle> fromWindowHandle = touchedWindow->windowHandle;
5793*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle> toWindowHandle = getWindowHandleLocked(toToken, displayId);
5794*38e8c45fSAndroid Build Coastguard Worker if (!toWindowHandle) {
5795*38e8c45fSAndroid Build Coastguard Worker ALOGW("Cannot transfer touch because the transfer target window was not found.");
5796*38e8c45fSAndroid Build Coastguard Worker return false;
5797*38e8c45fSAndroid Build Coastguard Worker }
5798*38e8c45fSAndroid Build Coastguard Worker
5799*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_FOCUS) {
5800*38e8c45fSAndroid Build Coastguard Worker ALOGD("%s: fromWindowHandle=%s, toWindowHandle=%s", __func__,
5801*38e8c45fSAndroid Build Coastguard Worker touchedWindow->windowHandle->getName().c_str(),
5802*38e8c45fSAndroid Build Coastguard Worker toWindowHandle->getName().c_str());
5803*38e8c45fSAndroid Build Coastguard Worker }
5804*38e8c45fSAndroid Build Coastguard Worker
5805*38e8c45fSAndroid Build Coastguard Worker // Erase old window.
5806*38e8c45fSAndroid Build Coastguard Worker ftl::Flags<InputTarget::Flags> oldTargetFlags = touchedWindow->targetFlags;
5807*38e8c45fSAndroid Build Coastguard Worker std::vector<PointerProperties> pointers = touchedWindow->getTouchingPointers(deviceId);
5808*38e8c45fSAndroid Build Coastguard Worker state->removeWindowByToken(fromToken);
5809*38e8c45fSAndroid Build Coastguard Worker
5810*38e8c45fSAndroid Build Coastguard Worker // Add new window.
5811*38e8c45fSAndroid Build Coastguard Worker nsecs_t downTimeInTarget = now();
5812*38e8c45fSAndroid Build Coastguard Worker ftl::Flags<InputTarget::Flags> newTargetFlags =
5813*38e8c45fSAndroid Build Coastguard Worker oldTargetFlags & (InputTarget::Flags::SPLIT);
5814*38e8c45fSAndroid Build Coastguard Worker if (canReceiveForegroundTouches(*toWindowHandle->getInfo())) {
5815*38e8c45fSAndroid Build Coastguard Worker newTargetFlags |= InputTarget::Flags::FOREGROUND;
5816*38e8c45fSAndroid Build Coastguard Worker }
5817*38e8c45fSAndroid Build Coastguard Worker // Transferring touch focus using this API should not effect the focused window.
5818*38e8c45fSAndroid Build Coastguard Worker newTargetFlags |= InputTarget::Flags::NO_FOCUS_CHANGE;
5819*38e8c45fSAndroid Build Coastguard Worker state->addOrUpdateWindow(toWindowHandle, InputTarget::DispatchMode::AS_IS, newTargetFlags,
5820*38e8c45fSAndroid Build Coastguard Worker deviceId, pointers, downTimeInTarget);
5821*38e8c45fSAndroid Build Coastguard Worker
5822*38e8c45fSAndroid Build Coastguard Worker // Store the dragging window.
5823*38e8c45fSAndroid Build Coastguard Worker if (isDragDrop) {
5824*38e8c45fSAndroid Build Coastguard Worker if (pointers.size() != 1) {
5825*38e8c45fSAndroid Build Coastguard Worker ALOGW("The drag and drop cannot be started when there is no pointer or more than 1"
5826*38e8c45fSAndroid Build Coastguard Worker " pointer on the window.");
5827*38e8c45fSAndroid Build Coastguard Worker return false;
5828*38e8c45fSAndroid Build Coastguard Worker }
5829*38e8c45fSAndroid Build Coastguard Worker // Track the pointer id for drag window and generate the drag state.
5830*38e8c45fSAndroid Build Coastguard Worker const size_t id = pointers.begin()->id;
5831*38e8c45fSAndroid Build Coastguard Worker mDragState = std::make_unique<DragState>(toWindowHandle, deviceId, id);
5832*38e8c45fSAndroid Build Coastguard Worker }
5833*38e8c45fSAndroid Build Coastguard Worker
5834*38e8c45fSAndroid Build Coastguard Worker // Synthesize cancel for old window and down for new window.
5835*38e8c45fSAndroid Build Coastguard Worker ScopedSyntheticEventTracer traceContext(mTracer);
5836*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<Connection> fromConnection = getConnectionLocked(fromToken);
5837*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<Connection> toConnection = getConnectionLocked(toToken);
5838*38e8c45fSAndroid Build Coastguard Worker if (fromConnection != nullptr && toConnection != nullptr) {
5839*38e8c45fSAndroid Build Coastguard Worker fromConnection->inputState.mergePointerStateTo(toConnection->inputState);
5840*38e8c45fSAndroid Build Coastguard Worker CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
5841*38e8c45fSAndroid Build Coastguard Worker "transferring touch from this window to another window",
5842*38e8c45fSAndroid Build Coastguard Worker traceContext.getTracker());
5843*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForWindowLocked(fromWindowHandle, options, fromConnection);
5844*38e8c45fSAndroid Build Coastguard Worker
5845*38e8c45fSAndroid Build Coastguard Worker // Check if the wallpaper window should deliver the corresponding event.
5846*38e8c45fSAndroid Build Coastguard Worker transferWallpaperTouch(oldTargetFlags, newTargetFlags, fromWindowHandle, toWindowHandle,
5847*38e8c45fSAndroid Build Coastguard Worker *state, deviceId, pointers, traceContext.getTracker());
5848*38e8c45fSAndroid Build Coastguard Worker
5849*38e8c45fSAndroid Build Coastguard Worker // Because new window may have a wallpaper window, it will merge input state from it
5850*38e8c45fSAndroid Build Coastguard Worker // parent window, after this the firstNewPointerIdx in input state will be reset, then
5851*38e8c45fSAndroid Build Coastguard Worker // it will cause new move event be thought inconsistent, so we should synthesize the
5852*38e8c45fSAndroid Build Coastguard Worker // down event after it reset.
5853*38e8c45fSAndroid Build Coastguard Worker synthesizePointerDownEventsForConnectionLocked(downTimeInTarget, toConnection,
5854*38e8c45fSAndroid Build Coastguard Worker newTargetFlags,
5855*38e8c45fSAndroid Build Coastguard Worker traceContext.getTracker());
5856*38e8c45fSAndroid Build Coastguard Worker }
5857*38e8c45fSAndroid Build Coastguard Worker } // release lock
5858*38e8c45fSAndroid Build Coastguard Worker
5859*38e8c45fSAndroid Build Coastguard Worker // Wake up poll loop since it may need to make new input dispatching choices.
5860*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
5861*38e8c45fSAndroid Build Coastguard Worker return true;
5862*38e8c45fSAndroid Build Coastguard Worker }
5863*38e8c45fSAndroid Build Coastguard Worker
5864*38e8c45fSAndroid Build Coastguard Worker /**
5865*38e8c45fSAndroid Build Coastguard Worker * Get the touched foreground window on the given display.
5866*38e8c45fSAndroid Build Coastguard Worker * Return null if there are no windows touched on that display, or if more than one foreground
5867*38e8c45fSAndroid Build Coastguard Worker * window is being touched.
5868*38e8c45fSAndroid Build Coastguard Worker */
findTouchedForegroundWindowLocked(ui::LogicalDisplayId displayId) const5869*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> InputDispatcher::findTouchedForegroundWindowLocked(
5870*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId displayId) const {
5871*38e8c45fSAndroid Build Coastguard Worker auto stateIt = mTouchStatesByDisplay.find(displayId);
5872*38e8c45fSAndroid Build Coastguard Worker if (stateIt == mTouchStatesByDisplay.end()) {
5873*38e8c45fSAndroid Build Coastguard Worker ALOGI("No touch state on display %s", displayId.toString().c_str());
5874*38e8c45fSAndroid Build Coastguard Worker return nullptr;
5875*38e8c45fSAndroid Build Coastguard Worker }
5876*38e8c45fSAndroid Build Coastguard Worker
5877*38e8c45fSAndroid Build Coastguard Worker const TouchState& state = stateIt->second;
5878*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> touchedForegroundWindow;
5879*38e8c45fSAndroid Build Coastguard Worker // If multiple foreground windows are touched, return nullptr
5880*38e8c45fSAndroid Build Coastguard Worker for (const TouchedWindow& window : state.windows) {
5881*38e8c45fSAndroid Build Coastguard Worker if (window.targetFlags.test(InputTarget::Flags::FOREGROUND)) {
5882*38e8c45fSAndroid Build Coastguard Worker if (touchedForegroundWindow != nullptr) {
5883*38e8c45fSAndroid Build Coastguard Worker ALOGI("Two or more foreground windows: %s and %s",
5884*38e8c45fSAndroid Build Coastguard Worker touchedForegroundWindow->getName().c_str(),
5885*38e8c45fSAndroid Build Coastguard Worker window.windowHandle->getName().c_str());
5886*38e8c45fSAndroid Build Coastguard Worker return nullptr;
5887*38e8c45fSAndroid Build Coastguard Worker }
5888*38e8c45fSAndroid Build Coastguard Worker touchedForegroundWindow = window.windowHandle;
5889*38e8c45fSAndroid Build Coastguard Worker }
5890*38e8c45fSAndroid Build Coastguard Worker }
5891*38e8c45fSAndroid Build Coastguard Worker return touchedForegroundWindow;
5892*38e8c45fSAndroid Build Coastguard Worker }
5893*38e8c45fSAndroid Build Coastguard Worker
5894*38e8c45fSAndroid Build Coastguard Worker // Binder call
transferTouchOnDisplay(const sp<IBinder> & destChannelToken,ui::LogicalDisplayId displayId)5895*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::transferTouchOnDisplay(const sp<IBinder>& destChannelToken,
5896*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId displayId) {
5897*38e8c45fSAndroid Build Coastguard Worker sp<IBinder> fromToken;
5898*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
5899*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
5900*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> toWindowHandle = getWindowHandleLocked(destChannelToken, displayId);
5901*38e8c45fSAndroid Build Coastguard Worker if (toWindowHandle == nullptr) {
5902*38e8c45fSAndroid Build Coastguard Worker ALOGW("Could not find window associated with token=%p on display %s",
5903*38e8c45fSAndroid Build Coastguard Worker destChannelToken.get(), displayId.toString().c_str());
5904*38e8c45fSAndroid Build Coastguard Worker return false;
5905*38e8c45fSAndroid Build Coastguard Worker }
5906*38e8c45fSAndroid Build Coastguard Worker
5907*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> from = findTouchedForegroundWindowLocked(displayId);
5908*38e8c45fSAndroid Build Coastguard Worker if (from == nullptr) {
5909*38e8c45fSAndroid Build Coastguard Worker ALOGE("Could not find a source window in %s for %p", __func__, destChannelToken.get());
5910*38e8c45fSAndroid Build Coastguard Worker return false;
5911*38e8c45fSAndroid Build Coastguard Worker }
5912*38e8c45fSAndroid Build Coastguard Worker
5913*38e8c45fSAndroid Build Coastguard Worker fromToken = from->getToken();
5914*38e8c45fSAndroid Build Coastguard Worker } // release lock
5915*38e8c45fSAndroid Build Coastguard Worker
5916*38e8c45fSAndroid Build Coastguard Worker return transferTouchGesture(fromToken, destChannelToken);
5917*38e8c45fSAndroid Build Coastguard Worker }
5918*38e8c45fSAndroid Build Coastguard Worker
resetAndDropEverythingLocked(const char * reason)5919*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
5920*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_FOCUS) {
5921*38e8c45fSAndroid Build Coastguard Worker ALOGD("Resetting and dropping all events (%s).", reason);
5922*38e8c45fSAndroid Build Coastguard Worker }
5923*38e8c45fSAndroid Build Coastguard Worker
5924*38e8c45fSAndroid Build Coastguard Worker ScopedSyntheticEventTracer traceContext(mTracer);
5925*38e8c45fSAndroid Build Coastguard Worker CancelationOptions options(CancelationOptions::Mode::CANCEL_ALL_EVENTS, reason,
5926*38e8c45fSAndroid Build Coastguard Worker traceContext.getTracker());
5927*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForAllConnectionsLocked(options);
5928*38e8c45fSAndroid Build Coastguard Worker
5929*38e8c45fSAndroid Build Coastguard Worker resetKeyRepeatLocked();
5930*38e8c45fSAndroid Build Coastguard Worker releasePendingEventLocked();
5931*38e8c45fSAndroid Build Coastguard Worker drainInboundQueueLocked();
5932*38e8c45fSAndroid Build Coastguard Worker resetNoFocusedWindowTimeoutLocked();
5933*38e8c45fSAndroid Build Coastguard Worker
5934*38e8c45fSAndroid Build Coastguard Worker mAnrTracker.clear();
5935*38e8c45fSAndroid Build Coastguard Worker mTouchStatesByDisplay.clear();
5936*38e8c45fSAndroid Build Coastguard Worker }
5937*38e8c45fSAndroid Build Coastguard Worker
logDispatchStateLocked() const5938*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::logDispatchStateLocked() const {
5939*38e8c45fSAndroid Build Coastguard Worker std::string dump;
5940*38e8c45fSAndroid Build Coastguard Worker dumpDispatchStateLocked(dump);
5941*38e8c45fSAndroid Build Coastguard Worker
5942*38e8c45fSAndroid Build Coastguard Worker std::istringstream stream(dump);
5943*38e8c45fSAndroid Build Coastguard Worker std::string line;
5944*38e8c45fSAndroid Build Coastguard Worker
5945*38e8c45fSAndroid Build Coastguard Worker while (std::getline(stream, line, '\n')) {
5946*38e8c45fSAndroid Build Coastguard Worker ALOGI("%s", line.c_str());
5947*38e8c45fSAndroid Build Coastguard Worker }
5948*38e8c45fSAndroid Build Coastguard Worker }
5949*38e8c45fSAndroid Build Coastguard Worker
dumpPointerCaptureStateLocked() const5950*38e8c45fSAndroid Build Coastguard Worker std::string InputDispatcher::dumpPointerCaptureStateLocked() const {
5951*38e8c45fSAndroid Build Coastguard Worker std::string dump;
5952*38e8c45fSAndroid Build Coastguard Worker
5953*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT "Pointer Capture Requested: %s\n",
5954*38e8c45fSAndroid Build Coastguard Worker toString(mCurrentPointerCaptureRequest.isEnable()));
5955*38e8c45fSAndroid Build Coastguard Worker
5956*38e8c45fSAndroid Build Coastguard Worker std::string windowName = "None";
5957*38e8c45fSAndroid Build Coastguard Worker if (mWindowTokenWithPointerCapture) {
5958*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle> captureWindowHandle =
5959*38e8c45fSAndroid Build Coastguard Worker getWindowHandleLocked(mWindowTokenWithPointerCapture);
5960*38e8c45fSAndroid Build Coastguard Worker windowName = captureWindowHandle ? captureWindowHandle->getName().c_str()
5961*38e8c45fSAndroid Build Coastguard Worker : "token has capture without window";
5962*38e8c45fSAndroid Build Coastguard Worker }
5963*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT "Current Window with Pointer Capture: %s\n", windowName.c_str());
5964*38e8c45fSAndroid Build Coastguard Worker
5965*38e8c45fSAndroid Build Coastguard Worker return dump;
5966*38e8c45fSAndroid Build Coastguard Worker }
5967*38e8c45fSAndroid Build Coastguard Worker
dumpDispatchStateLocked(std::string & dump) const5968*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::dumpDispatchStateLocked(std::string& dump) const {
5969*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT "DispatchEnabled: %s\n", toString(mDispatchEnabled));
5970*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT "DispatchFrozen: %s\n", toString(mDispatchFrozen));
5971*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT "InputFilterEnabled: %s\n", toString(mInputFilterEnabled));
5972*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT "FocusedDisplayId: %s\n", mFocusedDisplayId.toString().c_str());
5973*38e8c45fSAndroid Build Coastguard Worker
5974*38e8c45fSAndroid Build Coastguard Worker if (!mFocusedApplicationHandlesByDisplay.empty()) {
5975*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT "FocusedApplications:\n");
5976*38e8c45fSAndroid Build Coastguard Worker for (auto& it : mFocusedApplicationHandlesByDisplay) {
5977*38e8c45fSAndroid Build Coastguard Worker const ui::LogicalDisplayId displayId = it.first;
5978*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<InputApplicationHandle>& applicationHandle = it.second;
5979*38e8c45fSAndroid Build Coastguard Worker const std::chrono::duration timeout =
5980*38e8c45fSAndroid Build Coastguard Worker applicationHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
5981*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT2 "displayId=%s, name='%s', dispatchingTimeout=%" PRId64
5982*38e8c45fSAndroid Build Coastguard Worker "ms\n",
5983*38e8c45fSAndroid Build Coastguard Worker displayId.toString().c_str(), applicationHandle->getName().c_str(),
5984*38e8c45fSAndroid Build Coastguard Worker millis(timeout));
5985*38e8c45fSAndroid Build Coastguard Worker }
5986*38e8c45fSAndroid Build Coastguard Worker } else {
5987*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT "FocusedApplications: <none>\n");
5988*38e8c45fSAndroid Build Coastguard Worker }
5989*38e8c45fSAndroid Build Coastguard Worker
5990*38e8c45fSAndroid Build Coastguard Worker dump += mFocusResolver.dump();
5991*38e8c45fSAndroid Build Coastguard Worker dump += dumpPointerCaptureStateLocked();
5992*38e8c45fSAndroid Build Coastguard Worker
5993*38e8c45fSAndroid Build Coastguard Worker if (!mTouchStatesByDisplay.empty()) {
5994*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT "TouchStatesByDisplay:\n");
5995*38e8c45fSAndroid Build Coastguard Worker for (const auto& [displayId, state] : mTouchStatesByDisplay) {
5996*38e8c45fSAndroid Build Coastguard Worker std::string touchStateDump = addLinePrefix(state.dump(), INDENT2);
5997*38e8c45fSAndroid Build Coastguard Worker dump += INDENT2 + displayId.toString() + " : " + touchStateDump;
5998*38e8c45fSAndroid Build Coastguard Worker }
5999*38e8c45fSAndroid Build Coastguard Worker } else {
6000*38e8c45fSAndroid Build Coastguard Worker dump += INDENT "TouchStates: <no displays touched>\n";
6001*38e8c45fSAndroid Build Coastguard Worker }
6002*38e8c45fSAndroid Build Coastguard Worker
6003*38e8c45fSAndroid Build Coastguard Worker if (mDragState) {
6004*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT "DragState:\n");
6005*38e8c45fSAndroid Build Coastguard Worker mDragState->dump(dump, INDENT2);
6006*38e8c45fSAndroid Build Coastguard Worker }
6007*38e8c45fSAndroid Build Coastguard Worker
6008*38e8c45fSAndroid Build Coastguard Worker if (!mWindowHandlesByDisplay.empty()) {
6009*38e8c45fSAndroid Build Coastguard Worker for (const auto& [displayId, windowHandles] : mWindowHandlesByDisplay) {
6010*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT "Display: %s\n", displayId.toString().c_str());
6011*38e8c45fSAndroid Build Coastguard Worker if (const auto& it = mDisplayInfos.find(displayId); it != mDisplayInfos.end()) {
6012*38e8c45fSAndroid Build Coastguard Worker const auto& displayInfo = it->second;
6013*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT2 "logicalSize=%dx%d\n", displayInfo.logicalWidth,
6014*38e8c45fSAndroid Build Coastguard Worker displayInfo.logicalHeight);
6015*38e8c45fSAndroid Build Coastguard Worker displayInfo.transform.dump(dump, "transform", INDENT4);
6016*38e8c45fSAndroid Build Coastguard Worker } else {
6017*38e8c45fSAndroid Build Coastguard Worker dump += INDENT2 "No DisplayInfo found!\n";
6018*38e8c45fSAndroid Build Coastguard Worker }
6019*38e8c45fSAndroid Build Coastguard Worker
6020*38e8c45fSAndroid Build Coastguard Worker if (!windowHandles.empty()) {
6021*38e8c45fSAndroid Build Coastguard Worker dump += INDENT2 "Windows:\n";
6022*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < windowHandles.size(); i++) {
6023*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT3 "%zu: %s", i,
6024*38e8c45fSAndroid Build Coastguard Worker streamableToString(*windowHandles[i]).c_str());
6025*38e8c45fSAndroid Build Coastguard Worker }
6026*38e8c45fSAndroid Build Coastguard Worker } else {
6027*38e8c45fSAndroid Build Coastguard Worker dump += INDENT2 "Windows: <none>\n";
6028*38e8c45fSAndroid Build Coastguard Worker }
6029*38e8c45fSAndroid Build Coastguard Worker }
6030*38e8c45fSAndroid Build Coastguard Worker } else {
6031*38e8c45fSAndroid Build Coastguard Worker dump += INDENT "Displays: <none>\n";
6032*38e8c45fSAndroid Build Coastguard Worker }
6033*38e8c45fSAndroid Build Coastguard Worker
6034*38e8c45fSAndroid Build Coastguard Worker if (!mGlobalMonitorsByDisplay.empty()) {
6035*38e8c45fSAndroid Build Coastguard Worker for (const auto& [displayId, monitors] : mGlobalMonitorsByDisplay) {
6036*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT "Global monitors on display %s:\n",
6037*38e8c45fSAndroid Build Coastguard Worker displayId.toString().c_str());
6038*38e8c45fSAndroid Build Coastguard Worker dumpMonitors(dump, monitors);
6039*38e8c45fSAndroid Build Coastguard Worker }
6040*38e8c45fSAndroid Build Coastguard Worker } else {
6041*38e8c45fSAndroid Build Coastguard Worker dump += INDENT "Global Monitors: <none>\n";
6042*38e8c45fSAndroid Build Coastguard Worker }
6043*38e8c45fSAndroid Build Coastguard Worker
6044*38e8c45fSAndroid Build Coastguard Worker const nsecs_t currentTime = now();
6045*38e8c45fSAndroid Build Coastguard Worker
6046*38e8c45fSAndroid Build Coastguard Worker // Dump recently dispatched or dropped events from oldest to newest.
6047*38e8c45fSAndroid Build Coastguard Worker if (!mRecentQueue.empty()) {
6048*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT "RecentQueue: length=%zu\n", mRecentQueue.size());
6049*38e8c45fSAndroid Build Coastguard Worker for (const std::shared_ptr<const EventEntry>& entry : mRecentQueue) {
6050*38e8c45fSAndroid Build Coastguard Worker dump += INDENT2;
6051*38e8c45fSAndroid Build Coastguard Worker dump += entry->getDescription();
6052*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(", age=%" PRId64 "ms\n", ns2ms(currentTime - entry->eventTime));
6053*38e8c45fSAndroid Build Coastguard Worker }
6054*38e8c45fSAndroid Build Coastguard Worker } else {
6055*38e8c45fSAndroid Build Coastguard Worker dump += INDENT "RecentQueue: <empty>\n";
6056*38e8c45fSAndroid Build Coastguard Worker }
6057*38e8c45fSAndroid Build Coastguard Worker
6058*38e8c45fSAndroid Build Coastguard Worker // Dump event currently being dispatched.
6059*38e8c45fSAndroid Build Coastguard Worker if (mPendingEvent) {
6060*38e8c45fSAndroid Build Coastguard Worker dump += INDENT "PendingEvent:\n";
6061*38e8c45fSAndroid Build Coastguard Worker dump += INDENT2;
6062*38e8c45fSAndroid Build Coastguard Worker dump += mPendingEvent->getDescription();
6063*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(", age=%" PRId64 "ms\n",
6064*38e8c45fSAndroid Build Coastguard Worker ns2ms(currentTime - mPendingEvent->eventTime));
6065*38e8c45fSAndroid Build Coastguard Worker } else {
6066*38e8c45fSAndroid Build Coastguard Worker dump += INDENT "PendingEvent: <none>\n";
6067*38e8c45fSAndroid Build Coastguard Worker }
6068*38e8c45fSAndroid Build Coastguard Worker
6069*38e8c45fSAndroid Build Coastguard Worker // Dump inbound events from oldest to newest.
6070*38e8c45fSAndroid Build Coastguard Worker if (!mInboundQueue.empty()) {
6071*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT "InboundQueue: length=%zu\n", mInboundQueue.size());
6072*38e8c45fSAndroid Build Coastguard Worker for (const std::shared_ptr<const EventEntry>& entry : mInboundQueue) {
6073*38e8c45fSAndroid Build Coastguard Worker dump += INDENT2;
6074*38e8c45fSAndroid Build Coastguard Worker dump += entry->getDescription();
6075*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(", age=%" PRId64 "ms\n", ns2ms(currentTime - entry->eventTime));
6076*38e8c45fSAndroid Build Coastguard Worker }
6077*38e8c45fSAndroid Build Coastguard Worker } else {
6078*38e8c45fSAndroid Build Coastguard Worker dump += INDENT "InboundQueue: <empty>\n";
6079*38e8c45fSAndroid Build Coastguard Worker }
6080*38e8c45fSAndroid Build Coastguard Worker
6081*38e8c45fSAndroid Build Coastguard Worker if (!mCommandQueue.empty()) {
6082*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT "CommandQueue: size=%zu\n", mCommandQueue.size());
6083*38e8c45fSAndroid Build Coastguard Worker } else {
6084*38e8c45fSAndroid Build Coastguard Worker dump += INDENT "CommandQueue: <empty>\n";
6085*38e8c45fSAndroid Build Coastguard Worker }
6086*38e8c45fSAndroid Build Coastguard Worker
6087*38e8c45fSAndroid Build Coastguard Worker if (!mConnectionsByToken.empty()) {
6088*38e8c45fSAndroid Build Coastguard Worker dump += INDENT "Connections:\n";
6089*38e8c45fSAndroid Build Coastguard Worker for (const auto& [token, connection] : mConnectionsByToken) {
6090*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT2 "%i: channelName='%s', "
6091*38e8c45fSAndroid Build Coastguard Worker "status=%s, monitor=%s, responsive=%s\n",
6092*38e8c45fSAndroid Build Coastguard Worker connection->inputPublisher.getChannel().getFd(),
6093*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str(),
6094*38e8c45fSAndroid Build Coastguard Worker ftl::enum_string(connection->status).c_str(),
6095*38e8c45fSAndroid Build Coastguard Worker toString(connection->monitor), toString(connection->responsive));
6096*38e8c45fSAndroid Build Coastguard Worker
6097*38e8c45fSAndroid Build Coastguard Worker if (!connection->outboundQueue.empty()) {
6098*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT3 "OutboundQueue: length=%zu\n",
6099*38e8c45fSAndroid Build Coastguard Worker connection->outboundQueue.size());
6100*38e8c45fSAndroid Build Coastguard Worker dump += dumpQueue(connection->outboundQueue, currentTime);
6101*38e8c45fSAndroid Build Coastguard Worker }
6102*38e8c45fSAndroid Build Coastguard Worker
6103*38e8c45fSAndroid Build Coastguard Worker if (!connection->waitQueue.empty()) {
6104*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT3 "WaitQueue: length=%zu\n",
6105*38e8c45fSAndroid Build Coastguard Worker connection->waitQueue.size());
6106*38e8c45fSAndroid Build Coastguard Worker dump += dumpQueue(connection->waitQueue, currentTime);
6107*38e8c45fSAndroid Build Coastguard Worker }
6108*38e8c45fSAndroid Build Coastguard Worker std::string inputStateDump = streamableToString(connection->inputState);
6109*38e8c45fSAndroid Build Coastguard Worker if (!inputStateDump.empty()) {
6110*38e8c45fSAndroid Build Coastguard Worker dump += INDENT3 "InputState: ";
6111*38e8c45fSAndroid Build Coastguard Worker dump += inputStateDump + "\n";
6112*38e8c45fSAndroid Build Coastguard Worker }
6113*38e8c45fSAndroid Build Coastguard Worker }
6114*38e8c45fSAndroid Build Coastguard Worker } else {
6115*38e8c45fSAndroid Build Coastguard Worker dump += INDENT "Connections: <none>\n";
6116*38e8c45fSAndroid Build Coastguard Worker }
6117*38e8c45fSAndroid Build Coastguard Worker
6118*38e8c45fSAndroid Build Coastguard Worker if (!mTouchModePerDisplay.empty()) {
6119*38e8c45fSAndroid Build Coastguard Worker dump += INDENT "TouchModePerDisplay:\n";
6120*38e8c45fSAndroid Build Coastguard Worker for (const auto& [displayId, touchMode] : mTouchModePerDisplay) {
6121*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT2 "Display: %s TouchMode: %s\n",
6122*38e8c45fSAndroid Build Coastguard Worker displayId.toString().c_str(), std::to_string(touchMode).c_str());
6123*38e8c45fSAndroid Build Coastguard Worker }
6124*38e8c45fSAndroid Build Coastguard Worker } else {
6125*38e8c45fSAndroid Build Coastguard Worker dump += INDENT "TouchModePerDisplay: <none>\n";
6126*38e8c45fSAndroid Build Coastguard Worker }
6127*38e8c45fSAndroid Build Coastguard Worker
6128*38e8c45fSAndroid Build Coastguard Worker dump += INDENT "Configuration:\n";
6129*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT2 "KeyRepeatDelay: %" PRId64 "ms\n", ns2ms(mConfig.keyRepeatDelay));
6130*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT2 "KeyRepeatTimeout: %" PRId64 "ms\n",
6131*38e8c45fSAndroid Build Coastguard Worker ns2ms(mConfig.keyRepeatTimeout));
6132*38e8c45fSAndroid Build Coastguard Worker dump += mLatencyTracker.dump(INDENT2);
6133*38e8c45fSAndroid Build Coastguard Worker dump += mInputEventTimelineProcessor->dump(INDENT2);
6134*38e8c45fSAndroid Build Coastguard Worker dump += INDENT "InputTracer: ";
6135*38e8c45fSAndroid Build Coastguard Worker dump += mTracer == nullptr ? "Disabled" : "Enabled";
6136*38e8c45fSAndroid Build Coastguard Worker }
6137*38e8c45fSAndroid Build Coastguard Worker
dumpMonitors(std::string & dump,const std::vector<Monitor> & monitors) const6138*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::dumpMonitors(std::string& dump, const std::vector<Monitor>& monitors) const {
6139*38e8c45fSAndroid Build Coastguard Worker const size_t numMonitors = monitors.size();
6140*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < numMonitors; i++) {
6141*38e8c45fSAndroid Build Coastguard Worker const Monitor& monitor = monitors[i];
6142*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<Connection>& connection = monitor.connection;
6143*38e8c45fSAndroid Build Coastguard Worker dump += StringPrintf(INDENT2 "%zu: '%s', ", i, connection->getInputChannelName().c_str());
6144*38e8c45fSAndroid Build Coastguard Worker dump += "\n";
6145*38e8c45fSAndroid Build Coastguard Worker }
6146*38e8c45fSAndroid Build Coastguard Worker }
6147*38e8c45fSAndroid Build Coastguard Worker
6148*38e8c45fSAndroid Build Coastguard Worker class LooperEventCallback : public LooperCallback {
6149*38e8c45fSAndroid Build Coastguard Worker public:
LooperEventCallback(std::function<int (int events)> callback)6150*38e8c45fSAndroid Build Coastguard Worker LooperEventCallback(std::function<int(int events)> callback) : mCallback(callback) {}
handleEvent(int,int events,void *)6151*38e8c45fSAndroid Build Coastguard Worker int handleEvent(int /*fd*/, int events, void* /*data*/) override { return mCallback(events); }
6152*38e8c45fSAndroid Build Coastguard Worker
6153*38e8c45fSAndroid Build Coastguard Worker private:
6154*38e8c45fSAndroid Build Coastguard Worker std::function<int(int events)> mCallback;
6155*38e8c45fSAndroid Build Coastguard Worker };
6156*38e8c45fSAndroid Build Coastguard Worker
createInputChannel(const std::string & name)6157*38e8c45fSAndroid Build Coastguard Worker Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) {
6158*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_CHANNEL_CREATION) {
6159*38e8c45fSAndroid Build Coastguard Worker ALOGD("channel '%s' ~ createInputChannel", name.c_str());
6160*38e8c45fSAndroid Build Coastguard Worker }
6161*38e8c45fSAndroid Build Coastguard Worker
6162*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<InputChannel> serverChannel;
6163*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<InputChannel> clientChannel;
6164*38e8c45fSAndroid Build Coastguard Worker status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
6165*38e8c45fSAndroid Build Coastguard Worker
6166*38e8c45fSAndroid Build Coastguard Worker if (result) {
6167*38e8c45fSAndroid Build Coastguard Worker return base::Error(result) << "Failed to open input channel pair with name " << name;
6168*38e8c45fSAndroid Build Coastguard Worker }
6169*38e8c45fSAndroid Build Coastguard Worker
6170*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
6171*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
6172*38e8c45fSAndroid Build Coastguard Worker const sp<IBinder>& token = serverChannel->getConnectionToken();
6173*38e8c45fSAndroid Build Coastguard Worker const int fd = serverChannel->getFd();
6174*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<Connection> connection =
6175*38e8c45fSAndroid Build Coastguard Worker std::make_shared<Connection>(std::move(serverChannel), /*monitor=*/false,
6176*38e8c45fSAndroid Build Coastguard Worker mIdGenerator);
6177*38e8c45fSAndroid Build Coastguard Worker
6178*38e8c45fSAndroid Build Coastguard Worker auto [_, inserted] = mConnectionsByToken.try_emplace(token, connection);
6179*38e8c45fSAndroid Build Coastguard Worker if (!inserted) {
6180*38e8c45fSAndroid Build Coastguard Worker ALOGE("Created a new connection, but the token %p is already known", token.get());
6181*38e8c45fSAndroid Build Coastguard Worker }
6182*38e8c45fSAndroid Build Coastguard Worker
6183*38e8c45fSAndroid Build Coastguard Worker std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
6184*38e8c45fSAndroid Build Coastguard Worker this, std::placeholders::_1, token);
6185*38e8c45fSAndroid Build Coastguard Worker
6186*38e8c45fSAndroid Build Coastguard Worker mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, sp<LooperEventCallback>::make(callback),
6187*38e8c45fSAndroid Build Coastguard Worker nullptr);
6188*38e8c45fSAndroid Build Coastguard Worker } // release lock
6189*38e8c45fSAndroid Build Coastguard Worker
6190*38e8c45fSAndroid Build Coastguard Worker // Wake the looper because some connections have changed.
6191*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
6192*38e8c45fSAndroid Build Coastguard Worker return clientChannel;
6193*38e8c45fSAndroid Build Coastguard Worker }
6194*38e8c45fSAndroid Build Coastguard Worker
createInputMonitor(ui::LogicalDisplayId displayId,const std::string & name,gui::Pid pid)6195*38e8c45fSAndroid Build Coastguard Worker Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputMonitor(
6196*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId displayId, const std::string& name, gui::Pid pid) {
6197*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<InputChannel> serverChannel;
6198*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<InputChannel> clientChannel;
6199*38e8c45fSAndroid Build Coastguard Worker status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
6200*38e8c45fSAndroid Build Coastguard Worker if (result) {
6201*38e8c45fSAndroid Build Coastguard Worker return base::Error(result) << "Failed to open input channel pair with name " << name;
6202*38e8c45fSAndroid Build Coastguard Worker }
6203*38e8c45fSAndroid Build Coastguard Worker
6204*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
6205*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
6206*38e8c45fSAndroid Build Coastguard Worker
6207*38e8c45fSAndroid Build Coastguard Worker if (displayId < ui::LogicalDisplayId::DEFAULT) {
6208*38e8c45fSAndroid Build Coastguard Worker return base::Error(BAD_VALUE) << "Attempted to create input monitor with name " << name
6209*38e8c45fSAndroid Build Coastguard Worker << " without a specified display.";
6210*38e8c45fSAndroid Build Coastguard Worker }
6211*38e8c45fSAndroid Build Coastguard Worker
6212*38e8c45fSAndroid Build Coastguard Worker const sp<IBinder>& token = serverChannel->getConnectionToken();
6213*38e8c45fSAndroid Build Coastguard Worker const int fd = serverChannel->getFd();
6214*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<Connection> connection =
6215*38e8c45fSAndroid Build Coastguard Worker std::make_shared<Connection>(std::move(serverChannel), /*monitor=*/true,
6216*38e8c45fSAndroid Build Coastguard Worker mIdGenerator);
6217*38e8c45fSAndroid Build Coastguard Worker
6218*38e8c45fSAndroid Build Coastguard Worker auto [_, inserted] = mConnectionsByToken.emplace(token, connection);
6219*38e8c45fSAndroid Build Coastguard Worker if (!inserted) {
6220*38e8c45fSAndroid Build Coastguard Worker ALOGE("Created a new connection, but the token %p is already known", token.get());
6221*38e8c45fSAndroid Build Coastguard Worker }
6222*38e8c45fSAndroid Build Coastguard Worker
6223*38e8c45fSAndroid Build Coastguard Worker std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
6224*38e8c45fSAndroid Build Coastguard Worker this, std::placeholders::_1, token);
6225*38e8c45fSAndroid Build Coastguard Worker
6226*38e8c45fSAndroid Build Coastguard Worker mGlobalMonitorsByDisplay[displayId].emplace_back(connection, pid);
6227*38e8c45fSAndroid Build Coastguard Worker
6228*38e8c45fSAndroid Build Coastguard Worker mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, sp<LooperEventCallback>::make(callback),
6229*38e8c45fSAndroid Build Coastguard Worker nullptr);
6230*38e8c45fSAndroid Build Coastguard Worker }
6231*38e8c45fSAndroid Build Coastguard Worker
6232*38e8c45fSAndroid Build Coastguard Worker // Wake the looper because some connections have changed.
6233*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
6234*38e8c45fSAndroid Build Coastguard Worker return clientChannel;
6235*38e8c45fSAndroid Build Coastguard Worker }
6236*38e8c45fSAndroid Build Coastguard Worker
removeInputChannel(const sp<IBinder> & connectionToken)6237*38e8c45fSAndroid Build Coastguard Worker status_t InputDispatcher::removeInputChannel(const sp<IBinder>& connectionToken) {
6238*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
6239*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
6240*38e8c45fSAndroid Build Coastguard Worker
6241*38e8c45fSAndroid Build Coastguard Worker status_t status = removeInputChannelLocked(connectionToken, /*notify=*/false);
6242*38e8c45fSAndroid Build Coastguard Worker if (status) {
6243*38e8c45fSAndroid Build Coastguard Worker return status;
6244*38e8c45fSAndroid Build Coastguard Worker }
6245*38e8c45fSAndroid Build Coastguard Worker } // release lock
6246*38e8c45fSAndroid Build Coastguard Worker
6247*38e8c45fSAndroid Build Coastguard Worker // Wake the poll loop because removing the connection may have changed the current
6248*38e8c45fSAndroid Build Coastguard Worker // synchronization state.
6249*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
6250*38e8c45fSAndroid Build Coastguard Worker return OK;
6251*38e8c45fSAndroid Build Coastguard Worker }
6252*38e8c45fSAndroid Build Coastguard Worker
removeInputChannelLocked(const sp<IBinder> & connectionToken,bool notify)6253*38e8c45fSAndroid Build Coastguard Worker status_t InputDispatcher::removeInputChannelLocked(const sp<IBinder>& connectionToken,
6254*38e8c45fSAndroid Build Coastguard Worker bool notify) {
6255*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<Connection> connection = getConnectionLocked(connectionToken);
6256*38e8c45fSAndroid Build Coastguard Worker if (connection == nullptr) {
6257*38e8c45fSAndroid Build Coastguard Worker // Connection can be removed via socket hang up or an explicit call to 'removeInputChannel'
6258*38e8c45fSAndroid Build Coastguard Worker return BAD_VALUE;
6259*38e8c45fSAndroid Build Coastguard Worker }
6260*38e8c45fSAndroid Build Coastguard Worker
6261*38e8c45fSAndroid Build Coastguard Worker removeConnectionLocked(connection);
6262*38e8c45fSAndroid Build Coastguard Worker
6263*38e8c45fSAndroid Build Coastguard Worker if (connection->monitor) {
6264*38e8c45fSAndroid Build Coastguard Worker removeMonitorChannelLocked(connectionToken);
6265*38e8c45fSAndroid Build Coastguard Worker }
6266*38e8c45fSAndroid Build Coastguard Worker
6267*38e8c45fSAndroid Build Coastguard Worker mLooper->removeFd(connection->inputPublisher.getChannel().getFd());
6268*38e8c45fSAndroid Build Coastguard Worker
6269*38e8c45fSAndroid Build Coastguard Worker nsecs_t currentTime = now();
6270*38e8c45fSAndroid Build Coastguard Worker abortBrokenDispatchCycleLocked(currentTime, connection, notify);
6271*38e8c45fSAndroid Build Coastguard Worker
6272*38e8c45fSAndroid Build Coastguard Worker connection->status = Connection::Status::ZOMBIE;
6273*38e8c45fSAndroid Build Coastguard Worker return OK;
6274*38e8c45fSAndroid Build Coastguard Worker }
6275*38e8c45fSAndroid Build Coastguard Worker
removeMonitorChannelLocked(const sp<IBinder> & connectionToken)6276*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::removeMonitorChannelLocked(const sp<IBinder>& connectionToken) {
6277*38e8c45fSAndroid Build Coastguard Worker for (auto it = mGlobalMonitorsByDisplay.begin(); it != mGlobalMonitorsByDisplay.end();) {
6278*38e8c45fSAndroid Build Coastguard Worker auto& [displayId, monitors] = *it;
6279*38e8c45fSAndroid Build Coastguard Worker std::erase_if(monitors, [connectionToken](const Monitor& monitor) {
6280*38e8c45fSAndroid Build Coastguard Worker return monitor.connection->getToken() == connectionToken;
6281*38e8c45fSAndroid Build Coastguard Worker });
6282*38e8c45fSAndroid Build Coastguard Worker
6283*38e8c45fSAndroid Build Coastguard Worker if (monitors.empty()) {
6284*38e8c45fSAndroid Build Coastguard Worker it = mGlobalMonitorsByDisplay.erase(it);
6285*38e8c45fSAndroid Build Coastguard Worker } else {
6286*38e8c45fSAndroid Build Coastguard Worker ++it;
6287*38e8c45fSAndroid Build Coastguard Worker }
6288*38e8c45fSAndroid Build Coastguard Worker }
6289*38e8c45fSAndroid Build Coastguard Worker }
6290*38e8c45fSAndroid Build Coastguard Worker
pilferPointers(const sp<IBinder> & token)6291*38e8c45fSAndroid Build Coastguard Worker status_t InputDispatcher::pilferPointers(const sp<IBinder>& token) {
6292*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
6293*38e8c45fSAndroid Build Coastguard Worker return pilferPointersLocked(token);
6294*38e8c45fSAndroid Build Coastguard Worker }
6295*38e8c45fSAndroid Build Coastguard Worker
pilferPointersLocked(const sp<IBinder> & token)6296*38e8c45fSAndroid Build Coastguard Worker status_t InputDispatcher::pilferPointersLocked(const sp<IBinder>& token) {
6297*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<Connection> requestingConnection = getConnectionLocked(token);
6298*38e8c45fSAndroid Build Coastguard Worker if (!requestingConnection) {
6299*38e8c45fSAndroid Build Coastguard Worker LOG(WARNING)
6300*38e8c45fSAndroid Build Coastguard Worker << "Attempted to pilfer pointers from an un-registered channel or invalid token";
6301*38e8c45fSAndroid Build Coastguard Worker return BAD_VALUE;
6302*38e8c45fSAndroid Build Coastguard Worker }
6303*38e8c45fSAndroid Build Coastguard Worker
6304*38e8c45fSAndroid Build Coastguard Worker auto [statePtr, windowPtr, displayId] = findTouchStateWindowAndDisplayLocked(token);
6305*38e8c45fSAndroid Build Coastguard Worker if (statePtr == nullptr || windowPtr == nullptr) {
6306*38e8c45fSAndroid Build Coastguard Worker LOG(WARNING)
6307*38e8c45fSAndroid Build Coastguard Worker << "Attempted to pilfer points from a channel without any on-going pointer streams."
6308*38e8c45fSAndroid Build Coastguard Worker " Ignoring.";
6309*38e8c45fSAndroid Build Coastguard Worker return BAD_VALUE;
6310*38e8c45fSAndroid Build Coastguard Worker }
6311*38e8c45fSAndroid Build Coastguard Worker std::set<int32_t> deviceIds = windowPtr->getTouchingDeviceIds();
6312*38e8c45fSAndroid Build Coastguard Worker if (deviceIds.empty()) {
6313*38e8c45fSAndroid Build Coastguard Worker LOG(WARNING) << "Can't pilfer: no touching devices in window: " << windowPtr->dump();
6314*38e8c45fSAndroid Build Coastguard Worker return BAD_VALUE;
6315*38e8c45fSAndroid Build Coastguard Worker }
6316*38e8c45fSAndroid Build Coastguard Worker
6317*38e8c45fSAndroid Build Coastguard Worker ScopedSyntheticEventTracer traceContext(mTracer);
6318*38e8c45fSAndroid Build Coastguard Worker for (const DeviceId deviceId : deviceIds) {
6319*38e8c45fSAndroid Build Coastguard Worker TouchState& state = *statePtr;
6320*38e8c45fSAndroid Build Coastguard Worker TouchedWindow& window = *windowPtr;
6321*38e8c45fSAndroid Build Coastguard Worker // Send cancel events to all the input channels we're stealing from.
6322*38e8c45fSAndroid Build Coastguard Worker CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
6323*38e8c45fSAndroid Build Coastguard Worker "input channel stole pointer stream", traceContext.getTracker());
6324*38e8c45fSAndroid Build Coastguard Worker options.deviceId = deviceId;
6325*38e8c45fSAndroid Build Coastguard Worker options.displayId = displayId;
6326*38e8c45fSAndroid Build Coastguard Worker std::vector<PointerProperties> pointers = window.getTouchingPointers(deviceId);
6327*38e8c45fSAndroid Build Coastguard Worker std::bitset<MAX_POINTER_ID + 1> pointerIds = getPointerIds(pointers);
6328*38e8c45fSAndroid Build Coastguard Worker options.pointerIds = pointerIds;
6329*38e8c45fSAndroid Build Coastguard Worker
6330*38e8c45fSAndroid Build Coastguard Worker std::string canceledWindows;
6331*38e8c45fSAndroid Build Coastguard Worker for (const TouchedWindow& w : state.windows) {
6332*38e8c45fSAndroid Build Coastguard Worker if (w.windowHandle->getToken() != token) {
6333*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForWindowLocked(w.windowHandle, options);
6334*38e8c45fSAndroid Build Coastguard Worker canceledWindows += canceledWindows.empty() ? "[" : ", ";
6335*38e8c45fSAndroid Build Coastguard Worker canceledWindows += w.windowHandle->getName();
6336*38e8c45fSAndroid Build Coastguard Worker }
6337*38e8c45fSAndroid Build Coastguard Worker }
6338*38e8c45fSAndroid Build Coastguard Worker canceledWindows += canceledWindows.empty() ? "[]" : "]";
6339*38e8c45fSAndroid Build Coastguard Worker LOG(INFO) << "Channel " << requestingConnection->getInputChannelName()
6340*38e8c45fSAndroid Build Coastguard Worker << " is stealing input gesture for device " << deviceId << " from "
6341*38e8c45fSAndroid Build Coastguard Worker << canceledWindows;
6342*38e8c45fSAndroid Build Coastguard Worker
6343*38e8c45fSAndroid Build Coastguard Worker // Prevent the gesture from being sent to any other windows.
6344*38e8c45fSAndroid Build Coastguard Worker // This only blocks relevant pointers to be sent to other windows
6345*38e8c45fSAndroid Build Coastguard Worker window.addPilferingPointers(deviceId, pointerIds);
6346*38e8c45fSAndroid Build Coastguard Worker
6347*38e8c45fSAndroid Build Coastguard Worker state.cancelPointersForWindowsExcept(deviceId, pointerIds, token);
6348*38e8c45fSAndroid Build Coastguard Worker }
6349*38e8c45fSAndroid Build Coastguard Worker return OK;
6350*38e8c45fSAndroid Build Coastguard Worker }
6351*38e8c45fSAndroid Build Coastguard Worker
requestPointerCapture(const sp<IBinder> & windowToken,bool enabled)6352*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::requestPointerCapture(const sp<IBinder>& windowToken, bool enabled) {
6353*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
6354*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
6355*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_FOCUS) {
6356*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle> windowHandle = getWindowHandleLocked(windowToken);
6357*38e8c45fSAndroid Build Coastguard Worker ALOGI("Request to %s Pointer Capture from: %s.", enabled ? "enable" : "disable",
6358*38e8c45fSAndroid Build Coastguard Worker windowHandle != nullptr ? windowHandle->getName().c_str()
6359*38e8c45fSAndroid Build Coastguard Worker : "token without window");
6360*38e8c45fSAndroid Build Coastguard Worker }
6361*38e8c45fSAndroid Build Coastguard Worker
6362*38e8c45fSAndroid Build Coastguard Worker const sp<IBinder> focusedToken = mFocusResolver.getFocusedWindowToken(mFocusedDisplayId);
6363*38e8c45fSAndroid Build Coastguard Worker if (focusedToken != windowToken) {
6364*38e8c45fSAndroid Build Coastguard Worker ALOGW("Ignoring request to %s Pointer Capture: window does not have focus.",
6365*38e8c45fSAndroid Build Coastguard Worker enabled ? "enable" : "disable");
6366*38e8c45fSAndroid Build Coastguard Worker return;
6367*38e8c45fSAndroid Build Coastguard Worker }
6368*38e8c45fSAndroid Build Coastguard Worker
6369*38e8c45fSAndroid Build Coastguard Worker if (enabled == mCurrentPointerCaptureRequest.isEnable()) {
6370*38e8c45fSAndroid Build Coastguard Worker ALOGW("Ignoring request to %s Pointer Capture: "
6371*38e8c45fSAndroid Build Coastguard Worker "window has %s requested pointer capture.",
6372*38e8c45fSAndroid Build Coastguard Worker enabled ? "enable" : "disable", enabled ? "already" : "not");
6373*38e8c45fSAndroid Build Coastguard Worker return;
6374*38e8c45fSAndroid Build Coastguard Worker }
6375*38e8c45fSAndroid Build Coastguard Worker
6376*38e8c45fSAndroid Build Coastguard Worker if (enabled) {
6377*38e8c45fSAndroid Build Coastguard Worker if (std::find(mIneligibleDisplaysForPointerCapture.begin(),
6378*38e8c45fSAndroid Build Coastguard Worker mIneligibleDisplaysForPointerCapture.end(),
6379*38e8c45fSAndroid Build Coastguard Worker mFocusedDisplayId) != mIneligibleDisplaysForPointerCapture.end()) {
6380*38e8c45fSAndroid Build Coastguard Worker ALOGW("Ignoring request to enable Pointer Capture: display is not eligible");
6381*38e8c45fSAndroid Build Coastguard Worker return;
6382*38e8c45fSAndroid Build Coastguard Worker }
6383*38e8c45fSAndroid Build Coastguard Worker }
6384*38e8c45fSAndroid Build Coastguard Worker
6385*38e8c45fSAndroid Build Coastguard Worker setPointerCaptureLocked(enabled ? windowToken : nullptr);
6386*38e8c45fSAndroid Build Coastguard Worker } // release lock
6387*38e8c45fSAndroid Build Coastguard Worker
6388*38e8c45fSAndroid Build Coastguard Worker // Wake the thread to process command entries.
6389*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
6390*38e8c45fSAndroid Build Coastguard Worker }
6391*38e8c45fSAndroid Build Coastguard Worker
setDisplayEligibilityForPointerCapture(ui::LogicalDisplayId displayId,bool isEligible)6392*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::setDisplayEligibilityForPointerCapture(ui::LogicalDisplayId displayId,
6393*38e8c45fSAndroid Build Coastguard Worker bool isEligible) {
6394*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
6395*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
6396*38e8c45fSAndroid Build Coastguard Worker std::erase(mIneligibleDisplaysForPointerCapture, displayId);
6397*38e8c45fSAndroid Build Coastguard Worker if (!isEligible) {
6398*38e8c45fSAndroid Build Coastguard Worker mIneligibleDisplaysForPointerCapture.push_back(displayId);
6399*38e8c45fSAndroid Build Coastguard Worker }
6400*38e8c45fSAndroid Build Coastguard Worker } // release lock
6401*38e8c45fSAndroid Build Coastguard Worker }
6402*38e8c45fSAndroid Build Coastguard Worker
findMonitorPidByTokenLocked(const sp<IBinder> & token)6403*38e8c45fSAndroid Build Coastguard Worker std::optional<gui::Pid> InputDispatcher::findMonitorPidByTokenLocked(const sp<IBinder>& token) {
6404*38e8c45fSAndroid Build Coastguard Worker for (const auto& [_, monitors] : mGlobalMonitorsByDisplay) {
6405*38e8c45fSAndroid Build Coastguard Worker for (const Monitor& monitor : monitors) {
6406*38e8c45fSAndroid Build Coastguard Worker if (monitor.connection->getToken() == token) {
6407*38e8c45fSAndroid Build Coastguard Worker return monitor.pid;
6408*38e8c45fSAndroid Build Coastguard Worker }
6409*38e8c45fSAndroid Build Coastguard Worker }
6410*38e8c45fSAndroid Build Coastguard Worker }
6411*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
6412*38e8c45fSAndroid Build Coastguard Worker }
6413*38e8c45fSAndroid Build Coastguard Worker
getConnectionLocked(const sp<IBinder> & inputConnectionToken) const6414*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<Connection> InputDispatcher::getConnectionLocked(
6415*38e8c45fSAndroid Build Coastguard Worker const sp<IBinder>& inputConnectionToken) const {
6416*38e8c45fSAndroid Build Coastguard Worker if (inputConnectionToken == nullptr) {
6417*38e8c45fSAndroid Build Coastguard Worker return nullptr;
6418*38e8c45fSAndroid Build Coastguard Worker }
6419*38e8c45fSAndroid Build Coastguard Worker
6420*38e8c45fSAndroid Build Coastguard Worker for (const auto& [token, connection] : mConnectionsByToken) {
6421*38e8c45fSAndroid Build Coastguard Worker if (token == inputConnectionToken) {
6422*38e8c45fSAndroid Build Coastguard Worker return connection;
6423*38e8c45fSAndroid Build Coastguard Worker }
6424*38e8c45fSAndroid Build Coastguard Worker }
6425*38e8c45fSAndroid Build Coastguard Worker
6426*38e8c45fSAndroid Build Coastguard Worker return nullptr;
6427*38e8c45fSAndroid Build Coastguard Worker }
6428*38e8c45fSAndroid Build Coastguard Worker
getConnectionNameLocked(const sp<IBinder> & connectionToken) const6429*38e8c45fSAndroid Build Coastguard Worker std::string InputDispatcher::getConnectionNameLocked(const sp<IBinder>& connectionToken) const {
6430*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<Connection> connection = getConnectionLocked(connectionToken);
6431*38e8c45fSAndroid Build Coastguard Worker if (connection == nullptr) {
6432*38e8c45fSAndroid Build Coastguard Worker return "<nullptr>";
6433*38e8c45fSAndroid Build Coastguard Worker }
6434*38e8c45fSAndroid Build Coastguard Worker return connection->getInputChannelName();
6435*38e8c45fSAndroid Build Coastguard Worker }
6436*38e8c45fSAndroid Build Coastguard Worker
removeConnectionLocked(const std::shared_ptr<Connection> & connection)6437*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::removeConnectionLocked(const std::shared_ptr<Connection>& connection) {
6438*38e8c45fSAndroid Build Coastguard Worker mAnrTracker.eraseToken(connection->getToken());
6439*38e8c45fSAndroid Build Coastguard Worker mConnectionsByToken.erase(connection->getToken());
6440*38e8c45fSAndroid Build Coastguard Worker }
6441*38e8c45fSAndroid Build Coastguard Worker
doDispatchCycleFinishedCommand(nsecs_t finishTime,const std::shared_ptr<Connection> & connection,uint32_t seq,bool handled,nsecs_t consumeTime)6442*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::doDispatchCycleFinishedCommand(nsecs_t finishTime,
6443*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<Connection>& connection,
6444*38e8c45fSAndroid Build Coastguard Worker uint32_t seq, bool handled,
6445*38e8c45fSAndroid Build Coastguard Worker nsecs_t consumeTime) {
6446*38e8c45fSAndroid Build Coastguard Worker // Handle post-event policy actions.
6447*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<const KeyEntry> fallbackKeyEntry;
6448*38e8c45fSAndroid Build Coastguard Worker
6449*38e8c45fSAndroid Build Coastguard Worker { // Start critical section
6450*38e8c45fSAndroid Build Coastguard Worker auto dispatchEntryIt =
6451*38e8c45fSAndroid Build Coastguard Worker std::find_if(connection->waitQueue.begin(), connection->waitQueue.end(),
6452*38e8c45fSAndroid Build Coastguard Worker [seq](auto& e) { return e->seq == seq; });
6453*38e8c45fSAndroid Build Coastguard Worker if (dispatchEntryIt == connection->waitQueue.end()) {
6454*38e8c45fSAndroid Build Coastguard Worker return;
6455*38e8c45fSAndroid Build Coastguard Worker }
6456*38e8c45fSAndroid Build Coastguard Worker
6457*38e8c45fSAndroid Build Coastguard Worker DispatchEntry& dispatchEntry = **dispatchEntryIt;
6458*38e8c45fSAndroid Build Coastguard Worker
6459*38e8c45fSAndroid Build Coastguard Worker const nsecs_t eventDuration = finishTime - dispatchEntry.deliveryTime;
6460*38e8c45fSAndroid Build Coastguard Worker if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) {
6461*38e8c45fSAndroid Build Coastguard Worker ALOGI("%s spent %" PRId64 "ms processing %s", connection->getInputChannelName().c_str(),
6462*38e8c45fSAndroid Build Coastguard Worker ns2ms(eventDuration), dispatchEntry.eventEntry->getDescription().c_str());
6463*38e8c45fSAndroid Build Coastguard Worker }
6464*38e8c45fSAndroid Build Coastguard Worker if (shouldReportFinishedEvent(dispatchEntry, *connection)) {
6465*38e8c45fSAndroid Build Coastguard Worker mLatencyTracker.trackFinishedEvent(dispatchEntry.eventEntry->id, connection->getToken(),
6466*38e8c45fSAndroid Build Coastguard Worker dispatchEntry.deliveryTime, consumeTime, finishTime);
6467*38e8c45fSAndroid Build Coastguard Worker }
6468*38e8c45fSAndroid Build Coastguard Worker
6469*38e8c45fSAndroid Build Coastguard Worker if (dispatchEntry.eventEntry->type == EventEntry::Type::KEY) {
6470*38e8c45fSAndroid Build Coastguard Worker fallbackKeyEntry =
6471*38e8c45fSAndroid Build Coastguard Worker afterKeyEventLockedInterruptable(connection, &dispatchEntry, handled);
6472*38e8c45fSAndroid Build Coastguard Worker }
6473*38e8c45fSAndroid Build Coastguard Worker } // End critical section: The -LockedInterruptable methods may have released the lock.
6474*38e8c45fSAndroid Build Coastguard Worker
6475*38e8c45fSAndroid Build Coastguard Worker // Dequeue the event and start the next cycle.
6476*38e8c45fSAndroid Build Coastguard Worker // Because the lock might have been released, it is possible that the
6477*38e8c45fSAndroid Build Coastguard Worker // contents of the wait queue to have been drained, so we need to double-check
6478*38e8c45fSAndroid Build Coastguard Worker // a few things.
6479*38e8c45fSAndroid Build Coastguard Worker auto entryIt = std::find_if(connection->waitQueue.begin(), connection->waitQueue.end(),
6480*38e8c45fSAndroid Build Coastguard Worker [seq](auto& e) { return e->seq == seq; });
6481*38e8c45fSAndroid Build Coastguard Worker if (entryIt != connection->waitQueue.end()) {
6482*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<DispatchEntry> dispatchEntry = std::move(*entryIt);
6483*38e8c45fSAndroid Build Coastguard Worker connection->waitQueue.erase(entryIt);
6484*38e8c45fSAndroid Build Coastguard Worker
6485*38e8c45fSAndroid Build Coastguard Worker const sp<IBinder>& connectionToken = connection->getToken();
6486*38e8c45fSAndroid Build Coastguard Worker mAnrTracker.erase(dispatchEntry->timeoutTime, connectionToken);
6487*38e8c45fSAndroid Build Coastguard Worker if (!connection->responsive) {
6488*38e8c45fSAndroid Build Coastguard Worker connection->responsive = isConnectionResponsive(*connection);
6489*38e8c45fSAndroid Build Coastguard Worker if (connection->responsive) {
6490*38e8c45fSAndroid Build Coastguard Worker // The connection was unresponsive, and now it's responsive.
6491*38e8c45fSAndroid Build Coastguard Worker processConnectionResponsiveLocked(*connection);
6492*38e8c45fSAndroid Build Coastguard Worker }
6493*38e8c45fSAndroid Build Coastguard Worker }
6494*38e8c45fSAndroid Build Coastguard Worker traceWaitQueueLength(*connection);
6495*38e8c45fSAndroid Build Coastguard Worker if (fallbackKeyEntry && connection->status == Connection::Status::NORMAL) {
6496*38e8c45fSAndroid Build Coastguard Worker const auto windowHandle = getWindowHandleLocked(connection->getToken());
6497*38e8c45fSAndroid Build Coastguard Worker // Only dispatch fallbacks if there is a window for the connection.
6498*38e8c45fSAndroid Build Coastguard Worker if (windowHandle != nullptr) {
6499*38e8c45fSAndroid Build Coastguard Worker const auto inputTarget =
6500*38e8c45fSAndroid Build Coastguard Worker createInputTargetLocked(windowHandle, InputTarget::DispatchMode::AS_IS,
6501*38e8c45fSAndroid Build Coastguard Worker dispatchEntry->targetFlags,
6502*38e8c45fSAndroid Build Coastguard Worker fallbackKeyEntry->downTime);
6503*38e8c45fSAndroid Build Coastguard Worker if (inputTarget.has_value()) {
6504*38e8c45fSAndroid Build Coastguard Worker enqueueDispatchEntryLocked(connection, std::move(fallbackKeyEntry),
6505*38e8c45fSAndroid Build Coastguard Worker *inputTarget);
6506*38e8c45fSAndroid Build Coastguard Worker }
6507*38e8c45fSAndroid Build Coastguard Worker }
6508*38e8c45fSAndroid Build Coastguard Worker }
6509*38e8c45fSAndroid Build Coastguard Worker releaseDispatchEntry(std::move(dispatchEntry));
6510*38e8c45fSAndroid Build Coastguard Worker }
6511*38e8c45fSAndroid Build Coastguard Worker
6512*38e8c45fSAndroid Build Coastguard Worker // Start the next dispatch cycle for this connection.
6513*38e8c45fSAndroid Build Coastguard Worker startDispatchCycleLocked(now(), connection);
6514*38e8c45fSAndroid Build Coastguard Worker }
6515*38e8c45fSAndroid Build Coastguard Worker
sendFocusChangedCommandLocked(const sp<IBinder> & oldToken,const sp<IBinder> & newToken)6516*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::sendFocusChangedCommandLocked(const sp<IBinder>& oldToken,
6517*38e8c45fSAndroid Build Coastguard Worker const sp<IBinder>& newToken) {
6518*38e8c45fSAndroid Build Coastguard Worker auto command = [this, oldToken, newToken]() REQUIRES(mLock) {
6519*38e8c45fSAndroid Build Coastguard Worker scoped_unlock unlock(mLock);
6520*38e8c45fSAndroid Build Coastguard Worker mPolicy.notifyFocusChanged(oldToken, newToken);
6521*38e8c45fSAndroid Build Coastguard Worker };
6522*38e8c45fSAndroid Build Coastguard Worker postCommandLocked(std::move(command));
6523*38e8c45fSAndroid Build Coastguard Worker }
6524*38e8c45fSAndroid Build Coastguard Worker
sendDropWindowCommandLocked(const sp<IBinder> & token,float x,float y)6525*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::sendDropWindowCommandLocked(const sp<IBinder>& token, float x, float y) {
6526*38e8c45fSAndroid Build Coastguard Worker auto command = [this, token, x, y]() REQUIRES(mLock) {
6527*38e8c45fSAndroid Build Coastguard Worker scoped_unlock unlock(mLock);
6528*38e8c45fSAndroid Build Coastguard Worker mPolicy.notifyDropWindow(token, x, y);
6529*38e8c45fSAndroid Build Coastguard Worker };
6530*38e8c45fSAndroid Build Coastguard Worker postCommandLocked(std::move(command));
6531*38e8c45fSAndroid Build Coastguard Worker }
6532*38e8c45fSAndroid Build Coastguard Worker
onAnrLocked(const std::shared_ptr<Connection> & connection)6533*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::onAnrLocked(const std::shared_ptr<Connection>& connection) {
6534*38e8c45fSAndroid Build Coastguard Worker if (connection == nullptr) {
6535*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("Caller must check for nullness");
6536*38e8c45fSAndroid Build Coastguard Worker }
6537*38e8c45fSAndroid Build Coastguard Worker // Since we are allowing the policy to extend the timeout, maybe the waitQueue
6538*38e8c45fSAndroid Build Coastguard Worker // is already healthy again. Don't raise ANR in this situation
6539*38e8c45fSAndroid Build Coastguard Worker if (connection->waitQueue.empty()) {
6540*38e8c45fSAndroid Build Coastguard Worker ALOGI("Not raising ANR because the connection %s has recovered",
6541*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str());
6542*38e8c45fSAndroid Build Coastguard Worker return;
6543*38e8c45fSAndroid Build Coastguard Worker }
6544*38e8c45fSAndroid Build Coastguard Worker /**
6545*38e8c45fSAndroid Build Coastguard Worker * The "oldestEntry" is the entry that was first sent to the application. That entry, however,
6546*38e8c45fSAndroid Build Coastguard Worker * may not be the one that caused the timeout to occur. One possibility is that window timeout
6547*38e8c45fSAndroid Build Coastguard Worker * has changed. This could cause newer entries to time out before the already dispatched
6548*38e8c45fSAndroid Build Coastguard Worker * entries. In that situation, the newest entries caused ANR. But in all likelihood, the app
6549*38e8c45fSAndroid Build Coastguard Worker * processes the events linearly. So providing information about the oldest entry seems to be
6550*38e8c45fSAndroid Build Coastguard Worker * most useful.
6551*38e8c45fSAndroid Build Coastguard Worker */
6552*38e8c45fSAndroid Build Coastguard Worker DispatchEntry& oldestEntry = *connection->waitQueue.front();
6553*38e8c45fSAndroid Build Coastguard Worker const nsecs_t currentWait = now() - oldestEntry.deliveryTime;
6554*38e8c45fSAndroid Build Coastguard Worker std::string reason =
6555*38e8c45fSAndroid Build Coastguard Worker android::base::StringPrintf("%s is not responding. Waited %" PRId64 "ms for %s",
6556*38e8c45fSAndroid Build Coastguard Worker connection->getInputChannelName().c_str(),
6557*38e8c45fSAndroid Build Coastguard Worker ns2ms(currentWait),
6558*38e8c45fSAndroid Build Coastguard Worker oldestEntry.eventEntry->getDescription().c_str());
6559*38e8c45fSAndroid Build Coastguard Worker sp<IBinder> connectionToken = connection->getToken();
6560*38e8c45fSAndroid Build Coastguard Worker updateLastAnrStateLocked(getWindowHandleLocked(connectionToken), reason);
6561*38e8c45fSAndroid Build Coastguard Worker
6562*38e8c45fSAndroid Build Coastguard Worker processConnectionUnresponsiveLocked(*connection, std::move(reason));
6563*38e8c45fSAndroid Build Coastguard Worker
6564*38e8c45fSAndroid Build Coastguard Worker // Stop waking up for events on this connection, it is already unresponsive
6565*38e8c45fSAndroid Build Coastguard Worker cancelEventsForAnrLocked(connection);
6566*38e8c45fSAndroid Build Coastguard Worker }
6567*38e8c45fSAndroid Build Coastguard Worker
onAnrLocked(std::shared_ptr<InputApplicationHandle> application)6568*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::onAnrLocked(std::shared_ptr<InputApplicationHandle> application) {
6569*38e8c45fSAndroid Build Coastguard Worker std::string reason =
6570*38e8c45fSAndroid Build Coastguard Worker StringPrintf("%s does not have a focused window", application->getName().c_str());
6571*38e8c45fSAndroid Build Coastguard Worker updateLastAnrStateLocked(*application, reason);
6572*38e8c45fSAndroid Build Coastguard Worker
6573*38e8c45fSAndroid Build Coastguard Worker auto command = [this, app = std::move(application)]() REQUIRES(mLock) {
6574*38e8c45fSAndroid Build Coastguard Worker scoped_unlock unlock(mLock);
6575*38e8c45fSAndroid Build Coastguard Worker mPolicy.notifyNoFocusedWindowAnr(app);
6576*38e8c45fSAndroid Build Coastguard Worker };
6577*38e8c45fSAndroid Build Coastguard Worker postCommandLocked(std::move(command));
6578*38e8c45fSAndroid Build Coastguard Worker }
6579*38e8c45fSAndroid Build Coastguard Worker
updateLastAnrStateLocked(const sp<WindowInfoHandle> & window,const std::string & reason)6580*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::updateLastAnrStateLocked(const sp<WindowInfoHandle>& window,
6581*38e8c45fSAndroid Build Coastguard Worker const std::string& reason) {
6582*38e8c45fSAndroid Build Coastguard Worker const std::string windowLabel = getApplicationWindowLabel(nullptr, window);
6583*38e8c45fSAndroid Build Coastguard Worker updateLastAnrStateLocked(windowLabel, reason);
6584*38e8c45fSAndroid Build Coastguard Worker }
6585*38e8c45fSAndroid Build Coastguard Worker
updateLastAnrStateLocked(const InputApplicationHandle & application,const std::string & reason)6586*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::updateLastAnrStateLocked(const InputApplicationHandle& application,
6587*38e8c45fSAndroid Build Coastguard Worker const std::string& reason) {
6588*38e8c45fSAndroid Build Coastguard Worker const std::string windowLabel = getApplicationWindowLabel(&application, nullptr);
6589*38e8c45fSAndroid Build Coastguard Worker updateLastAnrStateLocked(windowLabel, reason);
6590*38e8c45fSAndroid Build Coastguard Worker }
6591*38e8c45fSAndroid Build Coastguard Worker
updateLastAnrStateLocked(const std::string & windowLabel,const std::string & reason)6592*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::updateLastAnrStateLocked(const std::string& windowLabel,
6593*38e8c45fSAndroid Build Coastguard Worker const std::string& reason) {
6594*38e8c45fSAndroid Build Coastguard Worker // Capture a record of the InputDispatcher state at the time of the ANR.
6595*38e8c45fSAndroid Build Coastguard Worker time_t t = time(nullptr);
6596*38e8c45fSAndroid Build Coastguard Worker struct tm tm;
6597*38e8c45fSAndroid Build Coastguard Worker localtime_r(&t, &tm);
6598*38e8c45fSAndroid Build Coastguard Worker char timestr[64];
6599*38e8c45fSAndroid Build Coastguard Worker strftime(timestr, sizeof(timestr), "%F %T", &tm);
6600*38e8c45fSAndroid Build Coastguard Worker mLastAnrState.clear();
6601*38e8c45fSAndroid Build Coastguard Worker mLastAnrState += INDENT "ANR:\n";
6602*38e8c45fSAndroid Build Coastguard Worker mLastAnrState += StringPrintf(INDENT2 "Time: %s\n", timestr);
6603*38e8c45fSAndroid Build Coastguard Worker mLastAnrState += StringPrintf(INDENT2 "Reason: %s\n", reason.c_str());
6604*38e8c45fSAndroid Build Coastguard Worker mLastAnrState += StringPrintf(INDENT2 "Window: %s\n", windowLabel.c_str());
6605*38e8c45fSAndroid Build Coastguard Worker dumpDispatchStateLocked(mLastAnrState);
6606*38e8c45fSAndroid Build Coastguard Worker }
6607*38e8c45fSAndroid Build Coastguard Worker
doInterceptKeyBeforeDispatchingCommand(const sp<IBinder> & focusedWindowToken,const KeyEntry & entry)6608*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::doInterceptKeyBeforeDispatchingCommand(const sp<IBinder>& focusedWindowToken,
6609*38e8c45fSAndroid Build Coastguard Worker const KeyEntry& entry) {
6610*38e8c45fSAndroid Build Coastguard Worker const KeyEvent event = createKeyEvent(entry);
6611*38e8c45fSAndroid Build Coastguard Worker nsecs_t delay = 0;
6612*38e8c45fSAndroid Build Coastguard Worker { // release lock
6613*38e8c45fSAndroid Build Coastguard Worker scoped_unlock unlock(mLock);
6614*38e8c45fSAndroid Build Coastguard Worker android::base::Timer t;
6615*38e8c45fSAndroid Build Coastguard Worker delay = mPolicy.interceptKeyBeforeDispatching(focusedWindowToken, event, entry.policyFlags);
6616*38e8c45fSAndroid Build Coastguard Worker if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
6617*38e8c45fSAndroid Build Coastguard Worker ALOGW("Excessive delay in interceptKeyBeforeDispatching; took %s ms",
6618*38e8c45fSAndroid Build Coastguard Worker std::to_string(t.duration().count()).c_str());
6619*38e8c45fSAndroid Build Coastguard Worker }
6620*38e8c45fSAndroid Build Coastguard Worker } // acquire lock
6621*38e8c45fSAndroid Build Coastguard Worker
6622*38e8c45fSAndroid Build Coastguard Worker if (delay < 0) {
6623*38e8c45fSAndroid Build Coastguard Worker entry.interceptKeyResult = KeyEntry::InterceptKeyResult::SKIP;
6624*38e8c45fSAndroid Build Coastguard Worker } else if (delay == 0) {
6625*38e8c45fSAndroid Build Coastguard Worker entry.interceptKeyResult = KeyEntry::InterceptKeyResult::CONTINUE;
6626*38e8c45fSAndroid Build Coastguard Worker } else {
6627*38e8c45fSAndroid Build Coastguard Worker entry.interceptKeyResult = KeyEntry::InterceptKeyResult::TRY_AGAIN_LATER;
6628*38e8c45fSAndroid Build Coastguard Worker entry.interceptKeyWakeupTime = now() + delay;
6629*38e8c45fSAndroid Build Coastguard Worker }
6630*38e8c45fSAndroid Build Coastguard Worker }
6631*38e8c45fSAndroid Build Coastguard Worker
sendWindowUnresponsiveCommandLocked(const sp<IBinder> & token,std::optional<gui::Pid> pid,std::string reason)6632*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::sendWindowUnresponsiveCommandLocked(const sp<IBinder>& token,
6633*38e8c45fSAndroid Build Coastguard Worker std::optional<gui::Pid> pid,
6634*38e8c45fSAndroid Build Coastguard Worker std::string reason) {
6635*38e8c45fSAndroid Build Coastguard Worker auto command = [this, token, pid, r = std::move(reason)]() REQUIRES(mLock) {
6636*38e8c45fSAndroid Build Coastguard Worker scoped_unlock unlock(mLock);
6637*38e8c45fSAndroid Build Coastguard Worker mPolicy.notifyWindowUnresponsive(token, pid, r);
6638*38e8c45fSAndroid Build Coastguard Worker };
6639*38e8c45fSAndroid Build Coastguard Worker postCommandLocked(std::move(command));
6640*38e8c45fSAndroid Build Coastguard Worker }
6641*38e8c45fSAndroid Build Coastguard Worker
sendWindowResponsiveCommandLocked(const sp<IBinder> & token,std::optional<gui::Pid> pid)6642*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::sendWindowResponsiveCommandLocked(const sp<IBinder>& token,
6643*38e8c45fSAndroid Build Coastguard Worker std::optional<gui::Pid> pid) {
6644*38e8c45fSAndroid Build Coastguard Worker auto command = [this, token, pid]() REQUIRES(mLock) {
6645*38e8c45fSAndroid Build Coastguard Worker scoped_unlock unlock(mLock);
6646*38e8c45fSAndroid Build Coastguard Worker mPolicy.notifyWindowResponsive(token, pid);
6647*38e8c45fSAndroid Build Coastguard Worker };
6648*38e8c45fSAndroid Build Coastguard Worker postCommandLocked(std::move(command));
6649*38e8c45fSAndroid Build Coastguard Worker }
6650*38e8c45fSAndroid Build Coastguard Worker
6651*38e8c45fSAndroid Build Coastguard Worker /**
6652*38e8c45fSAndroid Build Coastguard Worker * Tell the policy that a connection has become unresponsive so that it can start ANR.
6653*38e8c45fSAndroid Build Coastguard Worker * Check whether the connection of interest is a monitor or a window, and add the corresponding
6654*38e8c45fSAndroid Build Coastguard Worker * command entry to the command queue.
6655*38e8c45fSAndroid Build Coastguard Worker */
processConnectionUnresponsiveLocked(const Connection & connection,std::string reason)6656*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::processConnectionUnresponsiveLocked(const Connection& connection,
6657*38e8c45fSAndroid Build Coastguard Worker std::string reason) {
6658*38e8c45fSAndroid Build Coastguard Worker const sp<IBinder>& connectionToken = connection.getToken();
6659*38e8c45fSAndroid Build Coastguard Worker std::optional<gui::Pid> pid;
6660*38e8c45fSAndroid Build Coastguard Worker if (connection.monitor) {
6661*38e8c45fSAndroid Build Coastguard Worker ALOGW("Monitor %s is unresponsive: %s", connection.getInputChannelName().c_str(),
6662*38e8c45fSAndroid Build Coastguard Worker reason.c_str());
6663*38e8c45fSAndroid Build Coastguard Worker pid = findMonitorPidByTokenLocked(connectionToken);
6664*38e8c45fSAndroid Build Coastguard Worker } else {
6665*38e8c45fSAndroid Build Coastguard Worker // The connection is a window
6666*38e8c45fSAndroid Build Coastguard Worker ALOGW("Window %s is unresponsive: %s", connection.getInputChannelName().c_str(),
6667*38e8c45fSAndroid Build Coastguard Worker reason.c_str());
6668*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle> handle = getWindowHandleLocked(connectionToken);
6669*38e8c45fSAndroid Build Coastguard Worker if (handle != nullptr) {
6670*38e8c45fSAndroid Build Coastguard Worker pid = handle->getInfo()->ownerPid;
6671*38e8c45fSAndroid Build Coastguard Worker }
6672*38e8c45fSAndroid Build Coastguard Worker }
6673*38e8c45fSAndroid Build Coastguard Worker sendWindowUnresponsiveCommandLocked(connectionToken, pid, std::move(reason));
6674*38e8c45fSAndroid Build Coastguard Worker }
6675*38e8c45fSAndroid Build Coastguard Worker
6676*38e8c45fSAndroid Build Coastguard Worker /**
6677*38e8c45fSAndroid Build Coastguard Worker * Tell the policy that a connection has become responsive so that it can stop ANR.
6678*38e8c45fSAndroid Build Coastguard Worker */
processConnectionResponsiveLocked(const Connection & connection)6679*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::processConnectionResponsiveLocked(const Connection& connection) {
6680*38e8c45fSAndroid Build Coastguard Worker const sp<IBinder>& connectionToken = connection.getToken();
6681*38e8c45fSAndroid Build Coastguard Worker std::optional<gui::Pid> pid;
6682*38e8c45fSAndroid Build Coastguard Worker if (connection.monitor) {
6683*38e8c45fSAndroid Build Coastguard Worker pid = findMonitorPidByTokenLocked(connectionToken);
6684*38e8c45fSAndroid Build Coastguard Worker } else {
6685*38e8c45fSAndroid Build Coastguard Worker // The connection is a window
6686*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle> handle = getWindowHandleLocked(connectionToken);
6687*38e8c45fSAndroid Build Coastguard Worker if (handle != nullptr) {
6688*38e8c45fSAndroid Build Coastguard Worker pid = handle->getInfo()->ownerPid;
6689*38e8c45fSAndroid Build Coastguard Worker }
6690*38e8c45fSAndroid Build Coastguard Worker }
6691*38e8c45fSAndroid Build Coastguard Worker sendWindowResponsiveCommandLocked(connectionToken, pid);
6692*38e8c45fSAndroid Build Coastguard Worker }
6693*38e8c45fSAndroid Build Coastguard Worker
afterKeyEventLockedInterruptable(const std::shared_ptr<Connection> & connection,DispatchEntry * dispatchEntry,bool handled)6694*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<const KeyEntry> InputDispatcher::afterKeyEventLockedInterruptable(
6695*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<Connection>& connection, DispatchEntry* dispatchEntry, bool handled) {
6696*38e8c45fSAndroid Build Coastguard Worker // The dispatchEntry is currently valid, but it might point to a deleted object after we release
6697*38e8c45fSAndroid Build Coastguard Worker // the lock. For simplicity, make copies of the data of interest here and assume that
6698*38e8c45fSAndroid Build Coastguard Worker // 'dispatchEntry' is not valid after this section.
6699*38e8c45fSAndroid Build Coastguard Worker // Hold a strong reference to the EventEntry to ensure it's valid for the duration of this
6700*38e8c45fSAndroid Build Coastguard Worker // function, even if the DispatchEntry gets destroyed and releases its share of the ownership.
6701*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<const EventEntry> eventEntry = dispatchEntry->eventEntry;
6702*38e8c45fSAndroid Build Coastguard Worker const bool hasForegroundTarget = dispatchEntry->hasForegroundTarget();
6703*38e8c45fSAndroid Build Coastguard Worker const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*(eventEntry));
6704*38e8c45fSAndroid Build Coastguard Worker // To prevent misuse, ensure dispatchEntry is no longer valid.
6705*38e8c45fSAndroid Build Coastguard Worker dispatchEntry = nullptr;
6706*38e8c45fSAndroid Build Coastguard Worker if (keyEntry.flags & AKEY_EVENT_FLAG_FALLBACK) {
6707*38e8c45fSAndroid Build Coastguard Worker if (!handled) {
6708*38e8c45fSAndroid Build Coastguard Worker // Report the key as unhandled, since the fallback was not handled.
6709*38e8c45fSAndroid Build Coastguard Worker mReporter->reportUnhandledKey(keyEntry.id);
6710*38e8c45fSAndroid Build Coastguard Worker }
6711*38e8c45fSAndroid Build Coastguard Worker return {};
6712*38e8c45fSAndroid Build Coastguard Worker }
6713*38e8c45fSAndroid Build Coastguard Worker
6714*38e8c45fSAndroid Build Coastguard Worker // Get the fallback key state.
6715*38e8c45fSAndroid Build Coastguard Worker // Clear it out after dispatching the UP.
6716*38e8c45fSAndroid Build Coastguard Worker int32_t originalKeyCode = keyEntry.keyCode;
6717*38e8c45fSAndroid Build Coastguard Worker std::optional<int32_t> fallbackKeyCode = connection->inputState.getFallbackKey(originalKeyCode);
6718*38e8c45fSAndroid Build Coastguard Worker if (keyEntry.action == AKEY_EVENT_ACTION_UP) {
6719*38e8c45fSAndroid Build Coastguard Worker connection->inputState.removeFallbackKey(originalKeyCode);
6720*38e8c45fSAndroid Build Coastguard Worker }
6721*38e8c45fSAndroid Build Coastguard Worker
6722*38e8c45fSAndroid Build Coastguard Worker if (handled || !hasForegroundTarget) {
6723*38e8c45fSAndroid Build Coastguard Worker // If the application handles the original key for which we previously
6724*38e8c45fSAndroid Build Coastguard Worker // generated a fallback or if the window is not a foreground window,
6725*38e8c45fSAndroid Build Coastguard Worker // then cancel the associated fallback key, if any.
6726*38e8c45fSAndroid Build Coastguard Worker if (fallbackKeyCode) {
6727*38e8c45fSAndroid Build Coastguard Worker // Dispatch the unhandled key to the policy with the cancel flag.
6728*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_OUTBOUND_EVENT_DETAILS) {
6729*38e8c45fSAndroid Build Coastguard Worker ALOGD("Unhandled key event: Asking policy to cancel fallback action. "
6730*38e8c45fSAndroid Build Coastguard Worker "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
6731*38e8c45fSAndroid Build Coastguard Worker keyEntry.keyCode, keyEntry.action, keyEntry.repeatCount,
6732*38e8c45fSAndroid Build Coastguard Worker keyEntry.policyFlags);
6733*38e8c45fSAndroid Build Coastguard Worker }
6734*38e8c45fSAndroid Build Coastguard Worker KeyEvent event = createKeyEvent(keyEntry);
6735*38e8c45fSAndroid Build Coastguard Worker event.setFlags(event.getFlags() | AKEY_EVENT_FLAG_CANCELED);
6736*38e8c45fSAndroid Build Coastguard Worker
6737*38e8c45fSAndroid Build Coastguard Worker mLock.unlock();
6738*38e8c45fSAndroid Build Coastguard Worker
6739*38e8c45fSAndroid Build Coastguard Worker if (const auto unhandledKeyFallback =
6740*38e8c45fSAndroid Build Coastguard Worker mPolicy.dispatchUnhandledKey(connection->getToken(), event,
6741*38e8c45fSAndroid Build Coastguard Worker keyEntry.policyFlags);
6742*38e8c45fSAndroid Build Coastguard Worker unhandledKeyFallback) {
6743*38e8c45fSAndroid Build Coastguard Worker event = *unhandledKeyFallback;
6744*38e8c45fSAndroid Build Coastguard Worker }
6745*38e8c45fSAndroid Build Coastguard Worker
6746*38e8c45fSAndroid Build Coastguard Worker mLock.lock();
6747*38e8c45fSAndroid Build Coastguard Worker
6748*38e8c45fSAndroid Build Coastguard Worker // Cancel the fallback key, but only if we still have a window for the channel.
6749*38e8c45fSAndroid Build Coastguard Worker // It could have been removed during the policy call.
6750*38e8c45fSAndroid Build Coastguard Worker if (*fallbackKeyCode != AKEYCODE_UNKNOWN) {
6751*38e8c45fSAndroid Build Coastguard Worker const auto windowHandle = getWindowHandleLocked(connection->getToken());
6752*38e8c45fSAndroid Build Coastguard Worker if (windowHandle != nullptr) {
6753*38e8c45fSAndroid Build Coastguard Worker CancelationOptions options(CancelationOptions::Mode::CANCEL_FALLBACK_EVENTS,
6754*38e8c45fSAndroid Build Coastguard Worker "application handled the original non-fallback key "
6755*38e8c45fSAndroid Build Coastguard Worker "or is no longer a foreground target, "
6756*38e8c45fSAndroid Build Coastguard Worker "canceling previously dispatched fallback key",
6757*38e8c45fSAndroid Build Coastguard Worker keyEntry.traceTracker);
6758*38e8c45fSAndroid Build Coastguard Worker options.keyCode = *fallbackKeyCode;
6759*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForWindowLocked(windowHandle, options, connection);
6760*38e8c45fSAndroid Build Coastguard Worker }
6761*38e8c45fSAndroid Build Coastguard Worker }
6762*38e8c45fSAndroid Build Coastguard Worker connection->inputState.removeFallbackKey(originalKeyCode);
6763*38e8c45fSAndroid Build Coastguard Worker }
6764*38e8c45fSAndroid Build Coastguard Worker } else {
6765*38e8c45fSAndroid Build Coastguard Worker // If the application did not handle a non-fallback key, first check
6766*38e8c45fSAndroid Build Coastguard Worker // that we are in a good state to perform unhandled key event processing
6767*38e8c45fSAndroid Build Coastguard Worker // Then ask the policy what to do with it.
6768*38e8c45fSAndroid Build Coastguard Worker bool initialDown = keyEntry.action == AKEY_EVENT_ACTION_DOWN && keyEntry.repeatCount == 0;
6769*38e8c45fSAndroid Build Coastguard Worker if (!fallbackKeyCode && !initialDown) {
6770*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_OUTBOUND_EVENT_DETAILS) {
6771*38e8c45fSAndroid Build Coastguard Worker ALOGD("Unhandled key event: Skipping unhandled key event processing "
6772*38e8c45fSAndroid Build Coastguard Worker "since this is not an initial down. "
6773*38e8c45fSAndroid Build Coastguard Worker "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
6774*38e8c45fSAndroid Build Coastguard Worker originalKeyCode, keyEntry.action, keyEntry.repeatCount, keyEntry.policyFlags);
6775*38e8c45fSAndroid Build Coastguard Worker }
6776*38e8c45fSAndroid Build Coastguard Worker return {};
6777*38e8c45fSAndroid Build Coastguard Worker }
6778*38e8c45fSAndroid Build Coastguard Worker
6779*38e8c45fSAndroid Build Coastguard Worker // Dispatch the unhandled key to the policy.
6780*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_OUTBOUND_EVENT_DETAILS) {
6781*38e8c45fSAndroid Build Coastguard Worker ALOGD("Unhandled key event: Asking policy to perform fallback action. "
6782*38e8c45fSAndroid Build Coastguard Worker "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
6783*38e8c45fSAndroid Build Coastguard Worker keyEntry.keyCode, keyEntry.action, keyEntry.repeatCount, keyEntry.policyFlags);
6784*38e8c45fSAndroid Build Coastguard Worker }
6785*38e8c45fSAndroid Build Coastguard Worker KeyEvent event = createKeyEvent(keyEntry);
6786*38e8c45fSAndroid Build Coastguard Worker
6787*38e8c45fSAndroid Build Coastguard Worker mLock.unlock();
6788*38e8c45fSAndroid Build Coastguard Worker
6789*38e8c45fSAndroid Build Coastguard Worker bool fallback = false;
6790*38e8c45fSAndroid Build Coastguard Worker if (auto fb = mPolicy.dispatchUnhandledKey(connection->getToken(), event,
6791*38e8c45fSAndroid Build Coastguard Worker keyEntry.policyFlags);
6792*38e8c45fSAndroid Build Coastguard Worker fb) {
6793*38e8c45fSAndroid Build Coastguard Worker fallback = true;
6794*38e8c45fSAndroid Build Coastguard Worker event = *fb;
6795*38e8c45fSAndroid Build Coastguard Worker }
6796*38e8c45fSAndroid Build Coastguard Worker
6797*38e8c45fSAndroid Build Coastguard Worker mLock.lock();
6798*38e8c45fSAndroid Build Coastguard Worker
6799*38e8c45fSAndroid Build Coastguard Worker if (connection->status != Connection::Status::NORMAL) {
6800*38e8c45fSAndroid Build Coastguard Worker connection->inputState.removeFallbackKey(originalKeyCode);
6801*38e8c45fSAndroid Build Coastguard Worker return {};
6802*38e8c45fSAndroid Build Coastguard Worker }
6803*38e8c45fSAndroid Build Coastguard Worker
6804*38e8c45fSAndroid Build Coastguard Worker // Latch the fallback keycode for this key on an initial down.
6805*38e8c45fSAndroid Build Coastguard Worker // The fallback keycode cannot change at any other point in the lifecycle.
6806*38e8c45fSAndroid Build Coastguard Worker if (initialDown) {
6807*38e8c45fSAndroid Build Coastguard Worker if (fallback) {
6808*38e8c45fSAndroid Build Coastguard Worker fallbackKeyCode = event.getKeyCode();
6809*38e8c45fSAndroid Build Coastguard Worker } else {
6810*38e8c45fSAndroid Build Coastguard Worker fallbackKeyCode = AKEYCODE_UNKNOWN;
6811*38e8c45fSAndroid Build Coastguard Worker }
6812*38e8c45fSAndroid Build Coastguard Worker connection->inputState.setFallbackKey(originalKeyCode, *fallbackKeyCode);
6813*38e8c45fSAndroid Build Coastguard Worker }
6814*38e8c45fSAndroid Build Coastguard Worker
6815*38e8c45fSAndroid Build Coastguard Worker LOG_IF(FATAL, !fallbackKeyCode)
6816*38e8c45fSAndroid Build Coastguard Worker << "fallbackKeyCode is not initialized. initialDown = " << initialDown;
6817*38e8c45fSAndroid Build Coastguard Worker
6818*38e8c45fSAndroid Build Coastguard Worker // Cancel the fallback key if the policy decides not to send it anymore.
6819*38e8c45fSAndroid Build Coastguard Worker // We will continue to dispatch the key to the policy but we will no
6820*38e8c45fSAndroid Build Coastguard Worker // longer dispatch a fallback key to the application.
6821*38e8c45fSAndroid Build Coastguard Worker if (*fallbackKeyCode != AKEYCODE_UNKNOWN &&
6822*38e8c45fSAndroid Build Coastguard Worker (!fallback || *fallbackKeyCode != event.getKeyCode())) {
6823*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_OUTBOUND_EVENT_DETAILS) {
6824*38e8c45fSAndroid Build Coastguard Worker if (fallback) {
6825*38e8c45fSAndroid Build Coastguard Worker ALOGD("Unhandled key event: Policy requested to send key %d"
6826*38e8c45fSAndroid Build Coastguard Worker "as a fallback for %d, but on the DOWN it had requested "
6827*38e8c45fSAndroid Build Coastguard Worker "to send %d instead. Fallback canceled.",
6828*38e8c45fSAndroid Build Coastguard Worker event.getKeyCode(), originalKeyCode, *fallbackKeyCode);
6829*38e8c45fSAndroid Build Coastguard Worker } else {
6830*38e8c45fSAndroid Build Coastguard Worker ALOGD("Unhandled key event: Policy did not request fallback for %d, "
6831*38e8c45fSAndroid Build Coastguard Worker "but on the DOWN it had requested to send %d. "
6832*38e8c45fSAndroid Build Coastguard Worker "Fallback canceled.",
6833*38e8c45fSAndroid Build Coastguard Worker originalKeyCode, *fallbackKeyCode);
6834*38e8c45fSAndroid Build Coastguard Worker }
6835*38e8c45fSAndroid Build Coastguard Worker }
6836*38e8c45fSAndroid Build Coastguard Worker
6837*38e8c45fSAndroid Build Coastguard Worker const auto windowHandle = getWindowHandleLocked(connection->getToken());
6838*38e8c45fSAndroid Build Coastguard Worker if (windowHandle != nullptr) {
6839*38e8c45fSAndroid Build Coastguard Worker CancelationOptions options(CancelationOptions::Mode::CANCEL_FALLBACK_EVENTS,
6840*38e8c45fSAndroid Build Coastguard Worker "canceling fallback, policy no longer desires it",
6841*38e8c45fSAndroid Build Coastguard Worker keyEntry.traceTracker);
6842*38e8c45fSAndroid Build Coastguard Worker options.keyCode = *fallbackKeyCode;
6843*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForWindowLocked(windowHandle, options, connection);
6844*38e8c45fSAndroid Build Coastguard Worker }
6845*38e8c45fSAndroid Build Coastguard Worker
6846*38e8c45fSAndroid Build Coastguard Worker fallback = false;
6847*38e8c45fSAndroid Build Coastguard Worker *fallbackKeyCode = AKEYCODE_UNKNOWN;
6848*38e8c45fSAndroid Build Coastguard Worker if (keyEntry.action != AKEY_EVENT_ACTION_UP) {
6849*38e8c45fSAndroid Build Coastguard Worker connection->inputState.setFallbackKey(originalKeyCode, *fallbackKeyCode);
6850*38e8c45fSAndroid Build Coastguard Worker }
6851*38e8c45fSAndroid Build Coastguard Worker }
6852*38e8c45fSAndroid Build Coastguard Worker
6853*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_OUTBOUND_EVENT_DETAILS) {
6854*38e8c45fSAndroid Build Coastguard Worker {
6855*38e8c45fSAndroid Build Coastguard Worker std::string msg;
6856*38e8c45fSAndroid Build Coastguard Worker const std::map<int32_t, int32_t>& fallbackKeys =
6857*38e8c45fSAndroid Build Coastguard Worker connection->inputState.getFallbackKeys();
6858*38e8c45fSAndroid Build Coastguard Worker for (const auto& [key, value] : fallbackKeys) {
6859*38e8c45fSAndroid Build Coastguard Worker msg += StringPrintf(", %d->%d", key, value);
6860*38e8c45fSAndroid Build Coastguard Worker }
6861*38e8c45fSAndroid Build Coastguard Worker ALOGD("Unhandled key event: %zu currently tracked fallback keys%s.",
6862*38e8c45fSAndroid Build Coastguard Worker fallbackKeys.size(), msg.c_str());
6863*38e8c45fSAndroid Build Coastguard Worker }
6864*38e8c45fSAndroid Build Coastguard Worker }
6865*38e8c45fSAndroid Build Coastguard Worker
6866*38e8c45fSAndroid Build Coastguard Worker if (fallback) {
6867*38e8c45fSAndroid Build Coastguard Worker // Return the fallback key that we want dispatched to the channel.
6868*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<KeyEntry> newEntry =
6869*38e8c45fSAndroid Build Coastguard Worker std::make_unique<KeyEntry>(mIdGenerator.nextId(), keyEntry.injectionState,
6870*38e8c45fSAndroid Build Coastguard Worker event.getEventTime(), event.getDeviceId(),
6871*38e8c45fSAndroid Build Coastguard Worker event.getSource(), event.getDisplayId(),
6872*38e8c45fSAndroid Build Coastguard Worker keyEntry.policyFlags, keyEntry.action,
6873*38e8c45fSAndroid Build Coastguard Worker event.getFlags() | AKEY_EVENT_FLAG_FALLBACK,
6874*38e8c45fSAndroid Build Coastguard Worker *fallbackKeyCode, event.getScanCode(),
6875*38e8c45fSAndroid Build Coastguard Worker event.getMetaState(), event.getRepeatCount(),
6876*38e8c45fSAndroid Build Coastguard Worker event.getDownTime());
6877*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
6878*38e8c45fSAndroid Build Coastguard Worker newEntry->traceTracker =
6879*38e8c45fSAndroid Build Coastguard Worker mTracer->traceDerivedEvent(*newEntry, *keyEntry.traceTracker);
6880*38e8c45fSAndroid Build Coastguard Worker }
6881*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_OUTBOUND_EVENT_DETAILS) {
6882*38e8c45fSAndroid Build Coastguard Worker ALOGD("Unhandled key event: Dispatching fallback key. "
6883*38e8c45fSAndroid Build Coastguard Worker "originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x",
6884*38e8c45fSAndroid Build Coastguard Worker originalKeyCode, *fallbackKeyCode, keyEntry.metaState);
6885*38e8c45fSAndroid Build Coastguard Worker }
6886*38e8c45fSAndroid Build Coastguard Worker return newEntry;
6887*38e8c45fSAndroid Build Coastguard Worker } else {
6888*38e8c45fSAndroid Build Coastguard Worker if (DEBUG_OUTBOUND_EVENT_DETAILS) {
6889*38e8c45fSAndroid Build Coastguard Worker ALOGD("Unhandled key event: No fallback key.");
6890*38e8c45fSAndroid Build Coastguard Worker }
6891*38e8c45fSAndroid Build Coastguard Worker
6892*38e8c45fSAndroid Build Coastguard Worker // Report the key as unhandled, since there is no fallback key.
6893*38e8c45fSAndroid Build Coastguard Worker mReporter->reportUnhandledKey(keyEntry.id);
6894*38e8c45fSAndroid Build Coastguard Worker }
6895*38e8c45fSAndroid Build Coastguard Worker }
6896*38e8c45fSAndroid Build Coastguard Worker return {};
6897*38e8c45fSAndroid Build Coastguard Worker }
6898*38e8c45fSAndroid Build Coastguard Worker
traceInboundQueueLengthLocked()6899*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::traceInboundQueueLengthLocked() {
6900*38e8c45fSAndroid Build Coastguard Worker if (ATRACE_ENABLED()) {
6901*38e8c45fSAndroid Build Coastguard Worker ATRACE_INT("iq", mInboundQueue.size());
6902*38e8c45fSAndroid Build Coastguard Worker }
6903*38e8c45fSAndroid Build Coastguard Worker }
6904*38e8c45fSAndroid Build Coastguard Worker
traceOutboundQueueLength(const Connection & connection)6905*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::traceOutboundQueueLength(const Connection& connection) {
6906*38e8c45fSAndroid Build Coastguard Worker if (ATRACE_ENABLED()) {
6907*38e8c45fSAndroid Build Coastguard Worker char counterName[40];
6908*38e8c45fSAndroid Build Coastguard Worker snprintf(counterName, sizeof(counterName), "oq:%s",
6909*38e8c45fSAndroid Build Coastguard Worker connection.getInputChannelName().c_str());
6910*38e8c45fSAndroid Build Coastguard Worker ATRACE_INT(counterName, connection.outboundQueue.size());
6911*38e8c45fSAndroid Build Coastguard Worker }
6912*38e8c45fSAndroid Build Coastguard Worker }
6913*38e8c45fSAndroid Build Coastguard Worker
traceWaitQueueLength(const Connection & connection)6914*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::traceWaitQueueLength(const Connection& connection) {
6915*38e8c45fSAndroid Build Coastguard Worker if (ATRACE_ENABLED()) {
6916*38e8c45fSAndroid Build Coastguard Worker char counterName[40];
6917*38e8c45fSAndroid Build Coastguard Worker snprintf(counterName, sizeof(counterName), "wq:%s",
6918*38e8c45fSAndroid Build Coastguard Worker connection.getInputChannelName().c_str());
6919*38e8c45fSAndroid Build Coastguard Worker ATRACE_INT(counterName, connection.waitQueue.size());
6920*38e8c45fSAndroid Build Coastguard Worker }
6921*38e8c45fSAndroid Build Coastguard Worker }
6922*38e8c45fSAndroid Build Coastguard Worker
dump(std::string & dump) const6923*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::dump(std::string& dump) const {
6924*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
6925*38e8c45fSAndroid Build Coastguard Worker
6926*38e8c45fSAndroid Build Coastguard Worker dump += "Input Dispatcher State:\n";
6927*38e8c45fSAndroid Build Coastguard Worker dumpDispatchStateLocked(dump);
6928*38e8c45fSAndroid Build Coastguard Worker
6929*38e8c45fSAndroid Build Coastguard Worker if (!mLastAnrState.empty()) {
6930*38e8c45fSAndroid Build Coastguard Worker dump += "\nInput Dispatcher State at time of last ANR:\n";
6931*38e8c45fSAndroid Build Coastguard Worker dump += mLastAnrState;
6932*38e8c45fSAndroid Build Coastguard Worker }
6933*38e8c45fSAndroid Build Coastguard Worker }
6934*38e8c45fSAndroid Build Coastguard Worker
monitor()6935*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::monitor() {
6936*38e8c45fSAndroid Build Coastguard Worker // Acquire and release the lock to ensure that the dispatcher has not deadlocked.
6937*38e8c45fSAndroid Build Coastguard Worker std::unique_lock _l(mLock);
6938*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
6939*38e8c45fSAndroid Build Coastguard Worker mDispatcherIsAlive.wait(_l);
6940*38e8c45fSAndroid Build Coastguard Worker }
6941*38e8c45fSAndroid Build Coastguard Worker
6942*38e8c45fSAndroid Build Coastguard Worker /**
6943*38e8c45fSAndroid Build Coastguard Worker * Wake up the dispatcher and wait until it processes all events and commands.
6944*38e8c45fSAndroid Build Coastguard Worker * The notification of mDispatcherEnteredIdle is guaranteed to happen after wake(), so
6945*38e8c45fSAndroid Build Coastguard Worker * this method can be safely called from any thread, as long as you've ensured that
6946*38e8c45fSAndroid Build Coastguard Worker * the work you are interested in completing has already been queued.
6947*38e8c45fSAndroid Build Coastguard Worker */
waitForIdle() const6948*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::waitForIdle() const {
6949*38e8c45fSAndroid Build Coastguard Worker /**
6950*38e8c45fSAndroid Build Coastguard Worker * Timeout should represent the longest possible time that a device might spend processing
6951*38e8c45fSAndroid Build Coastguard Worker * events and commands.
6952*38e8c45fSAndroid Build Coastguard Worker */
6953*38e8c45fSAndroid Build Coastguard Worker constexpr std::chrono::duration TIMEOUT = 100ms;
6954*38e8c45fSAndroid Build Coastguard Worker std::unique_lock lock(mLock);
6955*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
6956*38e8c45fSAndroid Build Coastguard Worker std::cv_status result = mDispatcherEnteredIdle.wait_for(lock, TIMEOUT);
6957*38e8c45fSAndroid Build Coastguard Worker return result == std::cv_status::no_timeout;
6958*38e8c45fSAndroid Build Coastguard Worker }
6959*38e8c45fSAndroid Build Coastguard Worker
6960*38e8c45fSAndroid Build Coastguard Worker /**
6961*38e8c45fSAndroid Build Coastguard Worker * Sets focus to the window identified by the token. This must be called
6962*38e8c45fSAndroid Build Coastguard Worker * after updating any input window handles.
6963*38e8c45fSAndroid Build Coastguard Worker *
6964*38e8c45fSAndroid Build Coastguard Worker * Params:
6965*38e8c45fSAndroid Build Coastguard Worker * request.token - input channel token used to identify the window that should gain focus.
6966*38e8c45fSAndroid Build Coastguard Worker * request.focusedToken - the token that the caller expects currently to be focused. If the
6967*38e8c45fSAndroid Build Coastguard Worker * specified token does not match the currently focused window, this request will be dropped.
6968*38e8c45fSAndroid Build Coastguard Worker * If the specified focused token matches the currently focused window, the call will succeed.
6969*38e8c45fSAndroid Build Coastguard Worker * Set this to "null" if this call should succeed no matter what the currently focused token is.
6970*38e8c45fSAndroid Build Coastguard Worker * request.timestamp - SYSTEM_TIME_MONOTONIC timestamp in nanos set by the client (wm)
6971*38e8c45fSAndroid Build Coastguard Worker * when requesting the focus change. This determines which request gets
6972*38e8c45fSAndroid Build Coastguard Worker * precedence if there is a focus change request from another source such as pointer down.
6973*38e8c45fSAndroid Build Coastguard Worker */
setFocusedWindow(const FocusRequest & request)6974*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::setFocusedWindow(const FocusRequest& request) {
6975*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
6976*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
6977*38e8c45fSAndroid Build Coastguard Worker std::optional<FocusResolver::FocusChanges> changes =
6978*38e8c45fSAndroid Build Coastguard Worker mFocusResolver.setFocusedWindow(request,
6979*38e8c45fSAndroid Build Coastguard Worker getWindowHandlesLocked(
6980*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId{request.displayId}));
6981*38e8c45fSAndroid Build Coastguard Worker ScopedSyntheticEventTracer traceContext(mTracer);
6982*38e8c45fSAndroid Build Coastguard Worker if (changes) {
6983*38e8c45fSAndroid Build Coastguard Worker onFocusChangedLocked(*changes, traceContext.getTracker());
6984*38e8c45fSAndroid Build Coastguard Worker }
6985*38e8c45fSAndroid Build Coastguard Worker } // release lock
6986*38e8c45fSAndroid Build Coastguard Worker // Wake up poll loop since it may need to make new input dispatching choices.
6987*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
6988*38e8c45fSAndroid Build Coastguard Worker }
6989*38e8c45fSAndroid Build Coastguard Worker
onFocusChangedLocked(const FocusResolver::FocusChanges & changes,const std::unique_ptr<trace::EventTrackerInterface> & traceTracker,const sp<WindowInfoHandle> removedFocusedWindowHandle)6990*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::onFocusChangedLocked(
6991*38e8c45fSAndroid Build Coastguard Worker const FocusResolver::FocusChanges& changes,
6992*38e8c45fSAndroid Build Coastguard Worker const std::unique_ptr<trace::EventTrackerInterface>& traceTracker,
6993*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle> removedFocusedWindowHandle) {
6994*38e8c45fSAndroid Build Coastguard Worker if (changes.oldFocus) {
6995*38e8c45fSAndroid Build Coastguard Worker const auto resolvedWindow = removedFocusedWindowHandle != nullptr
6996*38e8c45fSAndroid Build Coastguard Worker ? removedFocusedWindowHandle
6997*38e8c45fSAndroid Build Coastguard Worker : getWindowHandleLocked(changes.oldFocus, changes.displayId);
6998*38e8c45fSAndroid Build Coastguard Worker if (resolvedWindow == nullptr) {
6999*38e8c45fSAndroid Build Coastguard Worker LOG(FATAL) << __func__ << ": Previously focused token did not have a window";
7000*38e8c45fSAndroid Build Coastguard Worker }
7001*38e8c45fSAndroid Build Coastguard Worker CancelationOptions options(CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS,
7002*38e8c45fSAndroid Build Coastguard Worker "focus left window", traceTracker);
7003*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForWindowLocked(resolvedWindow, options);
7004*38e8c45fSAndroid Build Coastguard Worker enqueueFocusEventLocked(changes.oldFocus, /*hasFocus=*/false, changes.reason);
7005*38e8c45fSAndroid Build Coastguard Worker }
7006*38e8c45fSAndroid Build Coastguard Worker if (changes.newFocus) {
7007*38e8c45fSAndroid Build Coastguard Worker resetNoFocusedWindowTimeoutLocked();
7008*38e8c45fSAndroid Build Coastguard Worker enqueueFocusEventLocked(changes.newFocus, /*hasFocus=*/true, changes.reason);
7009*38e8c45fSAndroid Build Coastguard Worker }
7010*38e8c45fSAndroid Build Coastguard Worker
7011*38e8c45fSAndroid Build Coastguard Worker if (mFocusedDisplayId == changes.displayId) {
7012*38e8c45fSAndroid Build Coastguard Worker // If a window has pointer capture, then it must have focus and must be on the top-focused
7013*38e8c45fSAndroid Build Coastguard Worker // display. We need to ensure that this contract is upheld when pointer capture is being
7014*38e8c45fSAndroid Build Coastguard Worker // disabled due to a loss of window focus. If the window loses focus before it loses pointer
7015*38e8c45fSAndroid Build Coastguard Worker // capture, then the window can be in a state where it has pointer capture but not focus,
7016*38e8c45fSAndroid Build Coastguard Worker // violating the contract. Therefore we must dispatch the pointer capture event before the
7017*38e8c45fSAndroid Build Coastguard Worker // focus event. Since focus events are added to the front of the queue (above), we add the
7018*38e8c45fSAndroid Build Coastguard Worker // pointer capture event to the front of the queue after the focus events are added. This
7019*38e8c45fSAndroid Build Coastguard Worker // ensures the pointer capture event ends up at the front.
7020*38e8c45fSAndroid Build Coastguard Worker disablePointerCaptureForcedLocked();
7021*38e8c45fSAndroid Build Coastguard Worker
7022*38e8c45fSAndroid Build Coastguard Worker sendFocusChangedCommandLocked(changes.oldFocus, changes.newFocus);
7023*38e8c45fSAndroid Build Coastguard Worker }
7024*38e8c45fSAndroid Build Coastguard Worker }
7025*38e8c45fSAndroid Build Coastguard Worker
disablePointerCaptureForcedLocked()7026*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::disablePointerCaptureForcedLocked() {
7027*38e8c45fSAndroid Build Coastguard Worker if (!mCurrentPointerCaptureRequest.isEnable() && !mWindowTokenWithPointerCapture) {
7028*38e8c45fSAndroid Build Coastguard Worker return;
7029*38e8c45fSAndroid Build Coastguard Worker }
7030*38e8c45fSAndroid Build Coastguard Worker
7031*38e8c45fSAndroid Build Coastguard Worker ALOGD_IF(DEBUG_FOCUS, "Disabling Pointer Capture because the window lost focus.");
7032*38e8c45fSAndroid Build Coastguard Worker
7033*38e8c45fSAndroid Build Coastguard Worker if (mCurrentPointerCaptureRequest.isEnable()) {
7034*38e8c45fSAndroid Build Coastguard Worker setPointerCaptureLocked(nullptr);
7035*38e8c45fSAndroid Build Coastguard Worker }
7036*38e8c45fSAndroid Build Coastguard Worker
7037*38e8c45fSAndroid Build Coastguard Worker if (!mWindowTokenWithPointerCapture) {
7038*38e8c45fSAndroid Build Coastguard Worker // No need to send capture changes because no window has capture.
7039*38e8c45fSAndroid Build Coastguard Worker return;
7040*38e8c45fSAndroid Build Coastguard Worker }
7041*38e8c45fSAndroid Build Coastguard Worker
7042*38e8c45fSAndroid Build Coastguard Worker if (mPendingEvent != nullptr) {
7043*38e8c45fSAndroid Build Coastguard Worker // Move the pending event to the front of the queue. This will give the chance
7044*38e8c45fSAndroid Build Coastguard Worker // for the pending event to be dropped if it is a captured event.
7045*38e8c45fSAndroid Build Coastguard Worker mInboundQueue.push_front(mPendingEvent);
7046*38e8c45fSAndroid Build Coastguard Worker mPendingEvent = nullptr;
7047*38e8c45fSAndroid Build Coastguard Worker }
7048*38e8c45fSAndroid Build Coastguard Worker
7049*38e8c45fSAndroid Build Coastguard Worker auto entry = std::make_unique<PointerCaptureChangedEntry>(mIdGenerator.nextId(), now(),
7050*38e8c45fSAndroid Build Coastguard Worker mCurrentPointerCaptureRequest);
7051*38e8c45fSAndroid Build Coastguard Worker mInboundQueue.push_front(std::move(entry));
7052*38e8c45fSAndroid Build Coastguard Worker }
7053*38e8c45fSAndroid Build Coastguard Worker
setPointerCaptureLocked(const sp<IBinder> & windowToken)7054*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::setPointerCaptureLocked(const sp<IBinder>& windowToken) {
7055*38e8c45fSAndroid Build Coastguard Worker mCurrentPointerCaptureRequest.window = windowToken;
7056*38e8c45fSAndroid Build Coastguard Worker mCurrentPointerCaptureRequest.seq++;
7057*38e8c45fSAndroid Build Coastguard Worker auto command = [this, request = mCurrentPointerCaptureRequest]() REQUIRES(mLock) {
7058*38e8c45fSAndroid Build Coastguard Worker scoped_unlock unlock(mLock);
7059*38e8c45fSAndroid Build Coastguard Worker mPolicy.setPointerCapture(request);
7060*38e8c45fSAndroid Build Coastguard Worker };
7061*38e8c45fSAndroid Build Coastguard Worker postCommandLocked(std::move(command));
7062*38e8c45fSAndroid Build Coastguard Worker }
7063*38e8c45fSAndroid Build Coastguard Worker
displayRemoved(ui::LogicalDisplayId displayId)7064*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::displayRemoved(ui::LogicalDisplayId displayId) {
7065*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
7066*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
7067*38e8c45fSAndroid Build Coastguard Worker // Set an empty list to remove all handles from the specific display.
7068*38e8c45fSAndroid Build Coastguard Worker setInputWindowsLocked(/*windowInfoHandles=*/{}, displayId);
7069*38e8c45fSAndroid Build Coastguard Worker setFocusedApplicationLocked(displayId, nullptr);
7070*38e8c45fSAndroid Build Coastguard Worker // Call focus resolver to clean up stale requests. This must be called after input windows
7071*38e8c45fSAndroid Build Coastguard Worker // have been removed for the removed display.
7072*38e8c45fSAndroid Build Coastguard Worker mFocusResolver.displayRemoved(displayId);
7073*38e8c45fSAndroid Build Coastguard Worker // Reset pointer capture eligibility, regardless of previous state.
7074*38e8c45fSAndroid Build Coastguard Worker std::erase(mIneligibleDisplaysForPointerCapture, displayId);
7075*38e8c45fSAndroid Build Coastguard Worker // Remove the associated touch mode state.
7076*38e8c45fSAndroid Build Coastguard Worker mTouchModePerDisplay.erase(displayId);
7077*38e8c45fSAndroid Build Coastguard Worker mVerifiersByDisplay.erase(displayId);
7078*38e8c45fSAndroid Build Coastguard Worker mInputFilterVerifiersByDisplay.erase(displayId);
7079*38e8c45fSAndroid Build Coastguard Worker } // release lock
7080*38e8c45fSAndroid Build Coastguard Worker
7081*38e8c45fSAndroid Build Coastguard Worker // Wake up poll loop since it may need to make new input dispatching choices.
7082*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
7083*38e8c45fSAndroid Build Coastguard Worker }
7084*38e8c45fSAndroid Build Coastguard Worker
onWindowInfosChanged(const gui::WindowInfosUpdate & update)7085*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::onWindowInfosChanged(const gui::WindowInfosUpdate& update) {
7086*38e8c45fSAndroid Build Coastguard Worker if (auto result = validateWindowInfosUpdate(update); !result.ok()) {
7087*38e8c45fSAndroid Build Coastguard Worker {
7088*38e8c45fSAndroid Build Coastguard Worker // acquire lock
7089*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
7090*38e8c45fSAndroid Build Coastguard Worker logDispatchStateLocked();
7091*38e8c45fSAndroid Build Coastguard Worker }
7092*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL("Incorrect WindowInfosUpdate provided: %s",
7093*38e8c45fSAndroid Build Coastguard Worker result.error().message().c_str());
7094*38e8c45fSAndroid Build Coastguard Worker };
7095*38e8c45fSAndroid Build Coastguard Worker // The listener sends the windows as a flattened array. Separate the windows by display for
7096*38e8c45fSAndroid Build Coastguard Worker // more convenient parsing.
7097*38e8c45fSAndroid Build Coastguard Worker std::unordered_map<ui::LogicalDisplayId, std::vector<sp<WindowInfoHandle>>> handlesPerDisplay;
7098*38e8c45fSAndroid Build Coastguard Worker for (const auto& info : update.windowInfos) {
7099*38e8c45fSAndroid Build Coastguard Worker handlesPerDisplay.emplace(info.displayId, std::vector<sp<WindowInfoHandle>>());
7100*38e8c45fSAndroid Build Coastguard Worker handlesPerDisplay[info.displayId].push_back(sp<WindowInfoHandle>::make(info));
7101*38e8c45fSAndroid Build Coastguard Worker if (input_flags::split_all_touches()) {
7102*38e8c45fSAndroid Build Coastguard Worker handlesPerDisplay[info.displayId]
7103*38e8c45fSAndroid Build Coastguard Worker .back()
7104*38e8c45fSAndroid Build Coastguard Worker ->editInfo()
7105*38e8c45fSAndroid Build Coastguard Worker ->setInputConfig(android::gui::WindowInfo::InputConfig::PREVENT_SPLITTING,
7106*38e8c45fSAndroid Build Coastguard Worker false);
7107*38e8c45fSAndroid Build Coastguard Worker }
7108*38e8c45fSAndroid Build Coastguard Worker }
7109*38e8c45fSAndroid Build Coastguard Worker
7110*38e8c45fSAndroid Build Coastguard Worker { // acquire lock
7111*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
7112*38e8c45fSAndroid Build Coastguard Worker
7113*38e8c45fSAndroid Build Coastguard Worker // Ensure that we have an entry created for all existing displays so that if a displayId has
7114*38e8c45fSAndroid Build Coastguard Worker // no windows, we can tell that the windows were removed from the display.
7115*38e8c45fSAndroid Build Coastguard Worker for (const auto& [displayId, _] : mWindowHandlesByDisplay) {
7116*38e8c45fSAndroid Build Coastguard Worker handlesPerDisplay[displayId];
7117*38e8c45fSAndroid Build Coastguard Worker }
7118*38e8c45fSAndroid Build Coastguard Worker
7119*38e8c45fSAndroid Build Coastguard Worker mDisplayInfos.clear();
7120*38e8c45fSAndroid Build Coastguard Worker for (const auto& displayInfo : update.displayInfos) {
7121*38e8c45fSAndroid Build Coastguard Worker mDisplayInfos.emplace(displayInfo.displayId, displayInfo);
7122*38e8c45fSAndroid Build Coastguard Worker }
7123*38e8c45fSAndroid Build Coastguard Worker
7124*38e8c45fSAndroid Build Coastguard Worker for (const auto& [displayId, handles] : handlesPerDisplay) {
7125*38e8c45fSAndroid Build Coastguard Worker setInputWindowsLocked(handles, displayId);
7126*38e8c45fSAndroid Build Coastguard Worker }
7127*38e8c45fSAndroid Build Coastguard Worker
7128*38e8c45fSAndroid Build Coastguard Worker if (update.vsyncId < mWindowInfosVsyncId) {
7129*38e8c45fSAndroid Build Coastguard Worker ALOGE("Received out of order window infos update. Last update vsync id: %" PRId64
7130*38e8c45fSAndroid Build Coastguard Worker ", current update vsync id: %" PRId64,
7131*38e8c45fSAndroid Build Coastguard Worker mWindowInfosVsyncId, update.vsyncId);
7132*38e8c45fSAndroid Build Coastguard Worker }
7133*38e8c45fSAndroid Build Coastguard Worker mWindowInfosVsyncId = update.vsyncId;
7134*38e8c45fSAndroid Build Coastguard Worker }
7135*38e8c45fSAndroid Build Coastguard Worker // Wake up poll loop since it may need to make new input dispatching choices.
7136*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
7137*38e8c45fSAndroid Build Coastguard Worker }
7138*38e8c45fSAndroid Build Coastguard Worker
shouldDropInput(const EventEntry & entry,const sp<android::gui::WindowInfoHandle> & windowHandle) const7139*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::shouldDropInput(
7140*38e8c45fSAndroid Build Coastguard Worker const EventEntry& entry, const sp<android::gui::WindowInfoHandle>& windowHandle) const {
7141*38e8c45fSAndroid Build Coastguard Worker if (windowHandle->getInfo()->inputConfig.test(WindowInfo::InputConfig::DROP_INPUT) ||
7142*38e8c45fSAndroid Build Coastguard Worker (windowHandle->getInfo()->inputConfig.test(
7143*38e8c45fSAndroid Build Coastguard Worker WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED) &&
7144*38e8c45fSAndroid Build Coastguard Worker isWindowObscuredLocked(windowHandle))) {
7145*38e8c45fSAndroid Build Coastguard Worker ALOGW("Dropping %s event targeting %s as requested by the input configuration {%s} on "
7146*38e8c45fSAndroid Build Coastguard Worker "display %s.",
7147*38e8c45fSAndroid Build Coastguard Worker ftl::enum_string(entry.type).c_str(), windowHandle->getName().c_str(),
7148*38e8c45fSAndroid Build Coastguard Worker windowHandle->getInfo()->inputConfig.string().c_str(),
7149*38e8c45fSAndroid Build Coastguard Worker windowHandle->getInfo()->displayId.toString().c_str());
7150*38e8c45fSAndroid Build Coastguard Worker return true;
7151*38e8c45fSAndroid Build Coastguard Worker }
7152*38e8c45fSAndroid Build Coastguard Worker return false;
7153*38e8c45fSAndroid Build Coastguard Worker }
7154*38e8c45fSAndroid Build Coastguard Worker
onWindowInfosChanged(const gui::WindowInfosUpdate & update)7155*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::DispatcherWindowListener::onWindowInfosChanged(
7156*38e8c45fSAndroid Build Coastguard Worker const gui::WindowInfosUpdate& update) {
7157*38e8c45fSAndroid Build Coastguard Worker mDispatcher.onWindowInfosChanged(update);
7158*38e8c45fSAndroid Build Coastguard Worker }
7159*38e8c45fSAndroid Build Coastguard Worker
cancelCurrentTouch()7160*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::cancelCurrentTouch() {
7161*38e8c45fSAndroid Build Coastguard Worker {
7162*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
7163*38e8c45fSAndroid Build Coastguard Worker ScopedSyntheticEventTracer traceContext(mTracer);
7164*38e8c45fSAndroid Build Coastguard Worker ALOGD("Canceling all ongoing pointer gestures on all displays.");
7165*38e8c45fSAndroid Build Coastguard Worker CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
7166*38e8c45fSAndroid Build Coastguard Worker "cancel current touch", traceContext.getTracker());
7167*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForAllConnectionsLocked(options);
7168*38e8c45fSAndroid Build Coastguard Worker
7169*38e8c45fSAndroid Build Coastguard Worker mTouchStatesByDisplay.clear();
7170*38e8c45fSAndroid Build Coastguard Worker }
7171*38e8c45fSAndroid Build Coastguard Worker // Wake up poll loop since there might be work to do.
7172*38e8c45fSAndroid Build Coastguard Worker mLooper->wake();
7173*38e8c45fSAndroid Build Coastguard Worker }
7174*38e8c45fSAndroid Build Coastguard Worker
setMonitorDispatchingTimeoutForTest(std::chrono::nanoseconds timeout)7175*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::setMonitorDispatchingTimeoutForTest(std::chrono::nanoseconds timeout) {
7176*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
7177*38e8c45fSAndroid Build Coastguard Worker mMonitorDispatchingTimeout = timeout;
7178*38e8c45fSAndroid Build Coastguard Worker }
7179*38e8c45fSAndroid Build Coastguard Worker
slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,const sp<WindowInfoHandle> & oldWindowHandle,const sp<WindowInfoHandle> & newWindowHandle,TouchState & state,const MotionEntry & entry,std::vector<InputTarget> & targets) const7180*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
7181*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle>& oldWindowHandle,
7182*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle>& newWindowHandle,
7183*38e8c45fSAndroid Build Coastguard Worker TouchState& state, const MotionEntry& entry,
7184*38e8c45fSAndroid Build Coastguard Worker std::vector<InputTarget>& targets) const {
7185*38e8c45fSAndroid Build Coastguard Worker LOG_IF(FATAL, entry.getPointerCount() != 1) << "Entry not eligible for slip: " << entry;
7186*38e8c45fSAndroid Build Coastguard Worker const DeviceId deviceId = entry.deviceId;
7187*38e8c45fSAndroid Build Coastguard Worker const PointerProperties& pointerProperties = entry.pointerProperties[0];
7188*38e8c45fSAndroid Build Coastguard Worker std::vector<PointerProperties> pointers{pointerProperties};
7189*38e8c45fSAndroid Build Coastguard Worker const bool oldHasWallpaper = oldWindowHandle->getInfo()->inputConfig.test(
7190*38e8c45fSAndroid Build Coastguard Worker gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);
7191*38e8c45fSAndroid Build Coastguard Worker const bool newHasWallpaper = targetFlags.test(InputTarget::Flags::FOREGROUND) &&
7192*38e8c45fSAndroid Build Coastguard Worker newWindowHandle->getInfo()->inputConfig.test(
7193*38e8c45fSAndroid Build Coastguard Worker gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);
7194*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle> oldWallpaper =
7195*38e8c45fSAndroid Build Coastguard Worker oldHasWallpaper ? state.getWallpaperWindow(deviceId) : nullptr;
7196*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle> newWallpaper =
7197*38e8c45fSAndroid Build Coastguard Worker newHasWallpaper ? findWallpaperWindowBelow(newWindowHandle) : nullptr;
7198*38e8c45fSAndroid Build Coastguard Worker if (oldWallpaper == newWallpaper) {
7199*38e8c45fSAndroid Build Coastguard Worker return;
7200*38e8c45fSAndroid Build Coastguard Worker }
7201*38e8c45fSAndroid Build Coastguard Worker
7202*38e8c45fSAndroid Build Coastguard Worker if (oldWallpaper != nullptr) {
7203*38e8c45fSAndroid Build Coastguard Worker const TouchedWindow& oldTouchedWindow = state.getTouchedWindow(oldWallpaper);
7204*38e8c45fSAndroid Build Coastguard Worker addPointerWindowTargetLocked(oldWallpaper, InputTarget::DispatchMode::SLIPPERY_EXIT,
7205*38e8c45fSAndroid Build Coastguard Worker oldTouchedWindow.targetFlags, getPointerIds(pointers),
7206*38e8c45fSAndroid Build Coastguard Worker oldTouchedWindow.getDownTimeInTarget(deviceId), targets);
7207*38e8c45fSAndroid Build Coastguard Worker state.removeTouchingPointerFromWindow(deviceId, pointerProperties.id, oldWallpaper);
7208*38e8c45fSAndroid Build Coastguard Worker }
7209*38e8c45fSAndroid Build Coastguard Worker
7210*38e8c45fSAndroid Build Coastguard Worker if (newWallpaper != nullptr) {
7211*38e8c45fSAndroid Build Coastguard Worker state.addOrUpdateWindow(newWallpaper, InputTarget::DispatchMode::SLIPPERY_ENTER,
7212*38e8c45fSAndroid Build Coastguard Worker InputTarget::Flags::WINDOW_IS_OBSCURED |
7213*38e8c45fSAndroid Build Coastguard Worker InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED,
7214*38e8c45fSAndroid Build Coastguard Worker deviceId, pointers, entry.eventTime);
7215*38e8c45fSAndroid Build Coastguard Worker }
7216*38e8c45fSAndroid Build Coastguard Worker }
7217*38e8c45fSAndroid Build Coastguard Worker
transferWallpaperTouch(ftl::Flags<InputTarget::Flags> oldTargetFlags,ftl::Flags<InputTarget::Flags> newTargetFlags,const sp<WindowInfoHandle> fromWindowHandle,const sp<WindowInfoHandle> toWindowHandle,TouchState & state,DeviceId deviceId,const std::vector<PointerProperties> & pointers,const std::unique_ptr<trace::EventTrackerInterface> & traceTracker)7218*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::transferWallpaperTouch(
7219*38e8c45fSAndroid Build Coastguard Worker ftl::Flags<InputTarget::Flags> oldTargetFlags,
7220*38e8c45fSAndroid Build Coastguard Worker ftl::Flags<InputTarget::Flags> newTargetFlags, const sp<WindowInfoHandle> fromWindowHandle,
7221*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle> toWindowHandle, TouchState& state, DeviceId deviceId,
7222*38e8c45fSAndroid Build Coastguard Worker const std::vector<PointerProperties>& pointers,
7223*38e8c45fSAndroid Build Coastguard Worker const std::unique_ptr<trace::EventTrackerInterface>& traceTracker) {
7224*38e8c45fSAndroid Build Coastguard Worker const bool oldHasWallpaper = oldTargetFlags.test(InputTarget::Flags::FOREGROUND) &&
7225*38e8c45fSAndroid Build Coastguard Worker fromWindowHandle->getInfo()->inputConfig.test(
7226*38e8c45fSAndroid Build Coastguard Worker gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);
7227*38e8c45fSAndroid Build Coastguard Worker const bool newHasWallpaper = newTargetFlags.test(InputTarget::Flags::FOREGROUND) &&
7228*38e8c45fSAndroid Build Coastguard Worker toWindowHandle->getInfo()->inputConfig.test(
7229*38e8c45fSAndroid Build Coastguard Worker gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);
7230*38e8c45fSAndroid Build Coastguard Worker
7231*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle> oldWallpaper =
7232*38e8c45fSAndroid Build Coastguard Worker oldHasWallpaper ? state.getWallpaperWindow(deviceId) : nullptr;
7233*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle> newWallpaper =
7234*38e8c45fSAndroid Build Coastguard Worker newHasWallpaper ? findWallpaperWindowBelow(toWindowHandle) : nullptr;
7235*38e8c45fSAndroid Build Coastguard Worker if (oldWallpaper == newWallpaper) {
7236*38e8c45fSAndroid Build Coastguard Worker return;
7237*38e8c45fSAndroid Build Coastguard Worker }
7238*38e8c45fSAndroid Build Coastguard Worker
7239*38e8c45fSAndroid Build Coastguard Worker if (oldWallpaper != nullptr) {
7240*38e8c45fSAndroid Build Coastguard Worker CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
7241*38e8c45fSAndroid Build Coastguard Worker "transferring touch focus to another window", traceTracker);
7242*38e8c45fSAndroid Build Coastguard Worker state.removeWindowByToken(oldWallpaper->getToken());
7243*38e8c45fSAndroid Build Coastguard Worker synthesizeCancelationEventsForWindowLocked(oldWallpaper, options);
7244*38e8c45fSAndroid Build Coastguard Worker }
7245*38e8c45fSAndroid Build Coastguard Worker
7246*38e8c45fSAndroid Build Coastguard Worker if (newWallpaper != nullptr) {
7247*38e8c45fSAndroid Build Coastguard Worker nsecs_t downTimeInTarget = now();
7248*38e8c45fSAndroid Build Coastguard Worker ftl::Flags<InputTarget::Flags> wallpaperFlags = newTargetFlags;
7249*38e8c45fSAndroid Build Coastguard Worker wallpaperFlags |= oldTargetFlags & InputTarget::Flags::SPLIT;
7250*38e8c45fSAndroid Build Coastguard Worker wallpaperFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED |
7251*38e8c45fSAndroid Build Coastguard Worker InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
7252*38e8c45fSAndroid Build Coastguard Worker state.addOrUpdateWindow(newWallpaper, InputTarget::DispatchMode::AS_IS, wallpaperFlags,
7253*38e8c45fSAndroid Build Coastguard Worker deviceId, pointers, downTimeInTarget);
7254*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<Connection> wallpaperConnection =
7255*38e8c45fSAndroid Build Coastguard Worker getConnectionLocked(newWallpaper->getToken());
7256*38e8c45fSAndroid Build Coastguard Worker if (wallpaperConnection != nullptr) {
7257*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<Connection> toConnection =
7258*38e8c45fSAndroid Build Coastguard Worker getConnectionLocked(toWindowHandle->getToken());
7259*38e8c45fSAndroid Build Coastguard Worker toConnection->inputState.mergePointerStateTo(wallpaperConnection->inputState);
7260*38e8c45fSAndroid Build Coastguard Worker synthesizePointerDownEventsForConnectionLocked(downTimeInTarget, wallpaperConnection,
7261*38e8c45fSAndroid Build Coastguard Worker wallpaperFlags, traceTracker);
7262*38e8c45fSAndroid Build Coastguard Worker }
7263*38e8c45fSAndroid Build Coastguard Worker }
7264*38e8c45fSAndroid Build Coastguard Worker }
7265*38e8c45fSAndroid Build Coastguard Worker
findWallpaperWindowBelow(const sp<WindowInfoHandle> & windowHandle) const7266*38e8c45fSAndroid Build Coastguard Worker sp<WindowInfoHandle> InputDispatcher::findWallpaperWindowBelow(
7267*38e8c45fSAndroid Build Coastguard Worker const sp<WindowInfoHandle>& windowHandle) const {
7268*38e8c45fSAndroid Build Coastguard Worker const std::vector<sp<WindowInfoHandle>>& windowHandles =
7269*38e8c45fSAndroid Build Coastguard Worker getWindowHandlesLocked(windowHandle->getInfo()->displayId);
7270*38e8c45fSAndroid Build Coastguard Worker bool foundWindow = false;
7271*38e8c45fSAndroid Build Coastguard Worker for (const sp<WindowInfoHandle>& otherHandle : windowHandles) {
7272*38e8c45fSAndroid Build Coastguard Worker if (!foundWindow && otherHandle != windowHandle) {
7273*38e8c45fSAndroid Build Coastguard Worker continue;
7274*38e8c45fSAndroid Build Coastguard Worker }
7275*38e8c45fSAndroid Build Coastguard Worker if (windowHandle == otherHandle) {
7276*38e8c45fSAndroid Build Coastguard Worker foundWindow = true;
7277*38e8c45fSAndroid Build Coastguard Worker continue;
7278*38e8c45fSAndroid Build Coastguard Worker }
7279*38e8c45fSAndroid Build Coastguard Worker
7280*38e8c45fSAndroid Build Coastguard Worker if (otherHandle->getInfo()->inputConfig.test(WindowInfo::InputConfig::IS_WALLPAPER)) {
7281*38e8c45fSAndroid Build Coastguard Worker return otherHandle;
7282*38e8c45fSAndroid Build Coastguard Worker }
7283*38e8c45fSAndroid Build Coastguard Worker }
7284*38e8c45fSAndroid Build Coastguard Worker return nullptr;
7285*38e8c45fSAndroid Build Coastguard Worker }
7286*38e8c45fSAndroid Build Coastguard Worker
setKeyRepeatConfiguration(std::chrono::nanoseconds timeout,std::chrono::nanoseconds delay,bool keyRepeatEnabled)7287*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::setKeyRepeatConfiguration(std::chrono::nanoseconds timeout,
7288*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds delay,
7289*38e8c45fSAndroid Build Coastguard Worker bool keyRepeatEnabled) {
7290*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
7291*38e8c45fSAndroid Build Coastguard Worker
7292*38e8c45fSAndroid Build Coastguard Worker mConfig.keyRepeatTimeout = timeout.count();
7293*38e8c45fSAndroid Build Coastguard Worker mConfig.keyRepeatDelay = delay.count();
7294*38e8c45fSAndroid Build Coastguard Worker mConfig.keyRepeatEnabled = keyRepeatEnabled;
7295*38e8c45fSAndroid Build Coastguard Worker }
7296*38e8c45fSAndroid Build Coastguard Worker
isPointerInWindow(const sp<android::IBinder> & token,ui::LogicalDisplayId displayId,DeviceId deviceId,int32_t pointerId)7297*38e8c45fSAndroid Build Coastguard Worker bool InputDispatcher::isPointerInWindow(const sp<android::IBinder>& token,
7298*38e8c45fSAndroid Build Coastguard Worker ui::LogicalDisplayId displayId, DeviceId deviceId,
7299*38e8c45fSAndroid Build Coastguard Worker int32_t pointerId) {
7300*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
7301*38e8c45fSAndroid Build Coastguard Worker auto touchStateIt = mTouchStatesByDisplay.find(displayId);
7302*38e8c45fSAndroid Build Coastguard Worker if (touchStateIt == mTouchStatesByDisplay.end()) {
7303*38e8c45fSAndroid Build Coastguard Worker return false;
7304*38e8c45fSAndroid Build Coastguard Worker }
7305*38e8c45fSAndroid Build Coastguard Worker for (const TouchedWindow& window : touchStateIt->second.windows) {
7306*38e8c45fSAndroid Build Coastguard Worker if (window.windowHandle->getToken() == token &&
7307*38e8c45fSAndroid Build Coastguard Worker (window.hasTouchingPointer(deviceId, pointerId) ||
7308*38e8c45fSAndroid Build Coastguard Worker window.hasHoveringPointer(deviceId, pointerId))) {
7309*38e8c45fSAndroid Build Coastguard Worker return true;
7310*38e8c45fSAndroid Build Coastguard Worker }
7311*38e8c45fSAndroid Build Coastguard Worker }
7312*38e8c45fSAndroid Build Coastguard Worker return false;
7313*38e8c45fSAndroid Build Coastguard Worker }
7314*38e8c45fSAndroid Build Coastguard Worker
setInputMethodConnectionIsActive(bool isActive)7315*38e8c45fSAndroid Build Coastguard Worker void InputDispatcher::setInputMethodConnectionIsActive(bool isActive) {
7316*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock _l(mLock);
7317*38e8c45fSAndroid Build Coastguard Worker if (mTracer) {
7318*38e8c45fSAndroid Build Coastguard Worker mTracer->setInputMethodConnectionIsActive(isActive);
7319*38e8c45fSAndroid Build Coastguard Worker }
7320*38e8c45fSAndroid Build Coastguard Worker }
7321*38e8c45fSAndroid Build Coastguard Worker
7322*38e8c45fSAndroid Build Coastguard Worker } // namespace android::inputdispatcher
7323