blob: 415b696e93dff18c1a0bec3c57e664642320f554 [file] [log] [blame]
Prabir Pradhandae52792023-12-15 07:36:40 +00001/*
2 * Copyright 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "InputTracer"
18
19#include "InputTracer.h"
20
21#include <android-base/logging.h>
Prabir Pradhanbf3c8322024-02-23 02:38:36 +000022#include <private/android_filesystem_config.h>
Prabir Pradhandae52792023-12-15 07:36:40 +000023
24namespace android::inputdispatcher::trace::impl {
25
26namespace {
27
Prabir Pradhanbb7a0202024-02-10 02:09:01 +000028// Helper to std::visit with lambdas.
29template <typename... V>
30struct Visitor : V... {
31 using V::operator()...;
32};
33
Prabir Pradhan4c49aad2024-02-08 20:42:35 +000034TracedEvent createTracedEvent(const MotionEntry& e, EventType type) {
Prabir Pradhandae52792023-12-15 07:36:40 +000035 return TracedMotionEvent{e.id,
36 e.eventTime,
37 e.policyFlags,
38 e.deviceId,
39 e.source,
40 e.displayId,
41 e.action,
42 e.actionButton,
43 e.flags,
44 e.metaState,
45 e.buttonState,
46 e.classification,
47 e.edgeFlags,
48 e.xPrecision,
49 e.yPrecision,
50 e.xCursorPosition,
51 e.yCursorPosition,
52 e.downTime,
53 e.pointerProperties,
Prabir Pradhan4c49aad2024-02-08 20:42:35 +000054 e.pointerCoords,
55 type};
Prabir Pradhandae52792023-12-15 07:36:40 +000056}
57
Prabir Pradhan4c49aad2024-02-08 20:42:35 +000058TracedEvent createTracedEvent(const KeyEntry& e, EventType type) {
Prabir Pradhandae52792023-12-15 07:36:40 +000059 return TracedKeyEvent{e.id, e.eventTime, e.policyFlags, e.deviceId, e.source,
60 e.displayId, e.action, e.keyCode, e.scanCode, e.metaState,
Prabir Pradhan4c49aad2024-02-08 20:42:35 +000061 e.downTime, e.flags, e.repeatCount, type};
Prabir Pradhandae52792023-12-15 07:36:40 +000062}
63
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +000064void writeEventToBackend(const TracedEvent& event, const TracedEventMetadata metadata,
Prabir Pradhan8c3b1432024-02-09 23:34:16 +000065 InputTracingBackendInterface& backend) {
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +000066 std::visit(Visitor{[&](const TracedMotionEvent& e) { backend.traceMotionEvent(e, metadata); },
67 [&](const TracedKeyEvent& e) { backend.traceKeyEvent(e, metadata); }},
Prabir Pradhana67623c2024-02-21 06:57:36 +000068 event);
69}
70
Prabir Pradhand6b2b052024-02-21 23:25:15 +000071inline auto getId(const trace::TracedEvent& v) {
72 return std::visit([](const auto& event) { return event.id; }, v);
73}
74
Prabir Pradhanbf3c8322024-02-23 02:38:36 +000075// Helper class to extract relevant information from InputTarget.
76struct InputTargetInfo {
77 gui::Uid uid;
78 bool isSecureWindow;
79};
80
81InputTargetInfo getTargetInfo(const InputTarget& target) {
82 if (target.windowHandle == nullptr) {
83 if (!target.connection->monitor) {
84 LOG(FATAL) << __func__ << ": Window is not set for non-monitor target";
85 }
86 // This is a global monitor, assume its target is the system.
87 return {.uid = gui::Uid{AID_SYSTEM}, .isSecureWindow = false};
88 }
Prabir Pradhanee76c372024-04-01 18:40:05 +000089 const auto& info = *target.windowHandle->getInfo();
90 const bool isSensitiveTarget =
91 info.inputConfig.test(gui::WindowInfo::InputConfig::SENSITIVE_FOR_TRACING);
92
93 // All FLAG_SECURE targets must be marked as sensitive for tracing.
94 if (info.layoutParamsFlags.test(gui::WindowInfo::Flag::SECURE) && !isSensitiveTarget) {
95 LOG(FATAL)
96 << "Input target with FLAG_SECURE does not set InputConfig::SENSITIVE_FOR_TRACING: "
97 << info;
98 }
Prabir Pradhancf359192024-03-20 00:42:57 +000099 return {target.windowHandle->getInfo()->ownerUid, isSensitiveTarget};
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000100}
101
Prabir Pradhandae52792023-12-15 07:36:40 +0000102} // namespace
103
104// --- InputTracer ---
105
106InputTracer::InputTracer(std::unique_ptr<InputTracingBackendInterface> backend)
Prabir Pradhanbb7a0202024-02-10 02:09:01 +0000107 : mBackend(std::move(backend)) {}
Prabir Pradhandae52792023-12-15 07:36:40 +0000108
109std::unique_ptr<EventTrackerInterface> InputTracer::traceInboundEvent(const EventEntry& entry) {
Prabir Pradhana67623c2024-02-21 06:57:36 +0000110 // This is a newly traced inbound event. Create a new state to track it and its derived events.
111 auto eventState = std::make_shared<EventState>(*this);
Prabir Pradhandae52792023-12-15 07:36:40 +0000112
113 if (entry.type == EventEntry::Type::MOTION) {
114 const auto& motion = static_cast<const MotionEntry&>(entry);
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000115 eventState->events.emplace_back(createTracedEvent(motion, EventType::INBOUND));
Prabir Pradhandae52792023-12-15 07:36:40 +0000116 } else if (entry.type == EventEntry::Type::KEY) {
117 const auto& key = static_cast<const KeyEntry&>(entry);
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000118 eventState->events.emplace_back(createTracedEvent(key, EventType::INBOUND));
Prabir Pradhandae52792023-12-15 07:36:40 +0000119 } else {
120 LOG(FATAL) << "Cannot trace EventEntry of type: " << ftl::enum_string(entry.type);
121 }
122
Prabir Pradhana67623c2024-02-21 06:57:36 +0000123 return std::make_unique<EventTrackerImpl>(std::move(eventState), /*isDerived=*/false);
Prabir Pradhandae52792023-12-15 07:36:40 +0000124}
125
Prabir Pradhand6b2b052024-02-21 23:25:15 +0000126std::unique_ptr<EventTrackerInterface> InputTracer::createTrackerForSyntheticEvent() {
127 // Create a new EventState to track events derived from this tracker.
128 return std::make_unique<EventTrackerImpl>(std::make_shared<EventState>(*this),
129 /*isDerived=*/false);
130}
131
Prabir Pradhandae52792023-12-15 07:36:40 +0000132void InputTracer::dispatchToTargetHint(const EventTrackerInterface& cookie,
133 const InputTarget& target) {
Prabir Pradhan1ea04a32024-02-10 03:02:59 +0000134 auto& eventState = getState(cookie);
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000135 const InputTargetInfo& targetInfo = getTargetInfo(target);
Prabir Pradhana67623c2024-02-21 06:57:36 +0000136 if (eventState->isEventProcessingComplete) {
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000137 // Disallow adding new targets after eventProcessingComplete() is called.
Prabir Pradhanac637022024-03-19 00:02:04 +0000138 if (eventState->metadata.targets.count(targetInfo.uid) == 0) {
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000139 LOG(FATAL) << __func__ << ": Cannot add new target after eventProcessingComplete";
140 }
Prabir Pradhana67623c2024-02-21 06:57:36 +0000141 return;
Prabir Pradhandae52792023-12-15 07:36:40 +0000142 }
Prabir Pradhanb95d4aa2024-03-11 22:48:04 +0000143 if (isDerivedCookie(cookie)) {
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000144 // Disallow adding new targets from a derived cookie.
Prabir Pradhanac637022024-03-19 00:02:04 +0000145 if (eventState->metadata.targets.count(targetInfo.uid) == 0) {
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000146 LOG(FATAL) << __func__ << ": Cannot add new target from a derived cookie";
147 }
Prabir Pradhanb95d4aa2024-03-11 22:48:04 +0000148 return;
149 }
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000150
Prabir Pradhanac637022024-03-19 00:02:04 +0000151 eventState->metadata.targets.emplace(targetInfo.uid);
152 eventState->metadata.isSecure |= targetInfo.isSecureWindow;
Prabir Pradhandae52792023-12-15 07:36:40 +0000153}
154
155void InputTracer::eventProcessingComplete(const EventTrackerInterface& cookie) {
Prabir Pradhana67623c2024-02-21 06:57:36 +0000156 if (isDerivedCookie(cookie)) {
157 LOG(FATAL) << "Event processing cannot be set from a derived cookie.";
158 }
Prabir Pradhan1ea04a32024-02-10 03:02:59 +0000159 auto& eventState = getState(cookie);
Prabir Pradhana67623c2024-02-21 06:57:36 +0000160 if (eventState->isEventProcessingComplete) {
Prabir Pradhanbb7a0202024-02-10 02:09:01 +0000161 LOG(FATAL) << "Traced event was already logged. "
162 "eventProcessingComplete() was likely called more than once.";
163 }
Prabir Pradhane7701642024-02-22 04:06:53 +0000164 eventState->onEventProcessingComplete();
Prabir Pradhana67623c2024-02-21 06:57:36 +0000165}
166
167std::unique_ptr<EventTrackerInterface> InputTracer::traceDerivedEvent(
168 const EventEntry& entry, const EventTrackerInterface& originalEventCookie) {
169 // This is an event derived from an already-established event. Use the same state to track
170 // this event too.
171 auto eventState = getState(originalEventCookie);
172
173 if (entry.type == EventEntry::Type::MOTION) {
174 const auto& motion = static_cast<const MotionEntry&>(entry);
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000175 eventState->events.emplace_back(createTracedEvent(motion, EventType::SYNTHESIZED));
Prabir Pradhana67623c2024-02-21 06:57:36 +0000176 } else if (entry.type == EventEntry::Type::KEY) {
177 const auto& key = static_cast<const KeyEntry&>(entry);
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000178 eventState->events.emplace_back(createTracedEvent(key, EventType::SYNTHESIZED));
Prabir Pradhana67623c2024-02-21 06:57:36 +0000179 } else {
180 LOG(FATAL) << "Cannot trace EventEntry of type: " << ftl::enum_string(entry.type);
181 }
182
183 if (eventState->isEventProcessingComplete) {
184 // It is possible for a derived event to be dispatched some time after the original event
185 // is dispatched, such as in the case of key fallback events. To account for these cases,
186 // derived events can be traced after the processing is complete for the original event.
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000187 const auto& event = eventState->events.back();
Prabir Pradhanac637022024-03-19 00:02:04 +0000188 writeEventToBackend(event, eventState->metadata, *mBackend);
Prabir Pradhana67623c2024-02-21 06:57:36 +0000189 }
190 return std::make_unique<EventTrackerImpl>(std::move(eventState), /*isDerived=*/true);
Prabir Pradhandae52792023-12-15 07:36:40 +0000191}
192
193void InputTracer::traceEventDispatch(const DispatchEntry& dispatchEntry,
Prabir Pradhand6b2b052024-02-21 23:25:15 +0000194 const EventTrackerInterface& cookie) {
195 auto& eventState = getState(cookie);
Prabir Pradhanbb7a0202024-02-10 02:09:01 +0000196 const EventEntry& entry = *dispatchEntry.eventEntry;
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000197 const int32_t eventId = entry.id;
Prabir Pradhan560d0d12024-03-07 18:08:27 +0000198 // TODO(b/328618922): Remove resolved key repeats after making repeatCount non-mutable.
199 // The KeyEntry's repeatCount is mutable and can be modified after an event is initially traced,
200 // so we need to find the repeatCount at the time of dispatching to trace it accurately.
201 int32_t resolvedKeyRepeatCount = 0;
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000202 if (entry.type == EventEntry::Type::KEY) {
203 resolvedKeyRepeatCount = static_cast<const KeyEntry&>(entry).repeatCount;
Prabir Pradhanbb7a0202024-02-10 02:09:01 +0000204 }
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000205
Prabir Pradhand6b2b052024-02-21 23:25:15 +0000206 auto tracedEventIt =
207 std::find_if(eventState->events.begin(), eventState->events.end(),
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000208 [eventId](const auto& event) { return eventId == getId(event); });
Prabir Pradhand6b2b052024-02-21 23:25:15 +0000209 if (tracedEventIt == eventState->events.end()) {
210 LOG(FATAL)
211 << __func__
212 << ": Failed to find a previously traced event that matches the dispatched event";
Prabir Pradhanbb7a0202024-02-10 02:09:01 +0000213 }
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000214
Prabir Pradhanac637022024-03-19 00:02:04 +0000215 if (eventState->metadata.targets.count(dispatchEntry.targetUid) == 0) {
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000216 LOG(FATAL) << __func__ << ": Event is being dispatched to UID that it is not targeting";
217 }
218
Prabir Pradhanbb7a0202024-02-10 02:09:01 +0000219 // The vsyncId only has meaning if the event is targeting a window.
220 const int32_t windowId = dispatchEntry.windowId.value_or(0);
221 const int32_t vsyncId = dispatchEntry.windowId.has_value() ? dispatchEntry.vsyncId : 0;
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000222
Prabir Pradhan8c3b1432024-02-09 23:34:16 +0000223 // TODO(b/210460522): Pass HMAC into traceEventDispatch.
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000224 const WindowDispatchArgs windowDispatchArgs{*tracedEventIt,
Prabir Pradhan52ec3ff2024-02-22 03:26:38 +0000225 dispatchEntry.deliveryTime,
226 dispatchEntry.resolvedFlags,
227 dispatchEntry.targetUid,
228 vsyncId,
229 windowId,
230 dispatchEntry.transform,
231 dispatchEntry.rawTransform,
232 /*hmac=*/{},
233 resolvedKeyRepeatCount};
234 if (eventState->isEventProcessingComplete) {
Prabir Pradhanac637022024-03-19 00:02:04 +0000235 mBackend->traceWindowDispatch(std::move(windowDispatchArgs), eventState->metadata);
Prabir Pradhan52ec3ff2024-02-22 03:26:38 +0000236 } else {
237 eventState->pendingDispatchArgs.emplace_back(std::move(windowDispatchArgs));
238 }
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000239}
Prabir Pradhandae52792023-12-15 07:36:40 +0000240
Prabir Pradhana67623c2024-02-21 06:57:36 +0000241std::shared_ptr<InputTracer::EventState>& InputTracer::getState(
242 const EventTrackerInterface& cookie) {
Prabir Pradhanbb7a0202024-02-10 02:09:01 +0000243 return static_cast<const EventTrackerImpl&>(cookie).mState;
Prabir Pradhandae52792023-12-15 07:36:40 +0000244}
245
Prabir Pradhana67623c2024-02-21 06:57:36 +0000246bool InputTracer::isDerivedCookie(const EventTrackerInterface& cookie) {
247 return static_cast<const EventTrackerImpl&>(cookie).mIsDerived;
248}
Prabir Pradhandae52792023-12-15 07:36:40 +0000249
Prabir Pradhana67623c2024-02-21 06:57:36 +0000250// --- InputTracer::EventState ---
Prabir Pradhandae52792023-12-15 07:36:40 +0000251
Prabir Pradhane7701642024-02-22 04:06:53 +0000252void InputTracer::EventState::onEventProcessingComplete() {
Prabir Pradhanac637022024-03-19 00:02:04 +0000253 metadata.isImeConnectionActive = tracer.mIsImeConnectionActive;
Prabir Pradhan04a66422024-03-15 22:45:27 +0000254
Prabir Pradhane7701642024-02-22 04:06:53 +0000255 // Write all of the events known so far to the trace.
256 for (const auto& event : events) {
Prabir Pradhanac637022024-03-19 00:02:04 +0000257 writeEventToBackend(event, metadata, *tracer.mBackend);
Prabir Pradhane7701642024-02-22 04:06:53 +0000258 }
Prabir Pradhan52ec3ff2024-02-22 03:26:38 +0000259 // Write all pending dispatch args to the trace.
260 for (const auto& windowDispatchArgs : pendingDispatchArgs) {
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000261 auto tracedEventIt =
262 std::find_if(events.begin(), events.end(),
263 [id = getId(windowDispatchArgs.eventEntry)](const auto& event) {
264 return id == getId(event);
265 });
266 if (tracedEventIt == events.end()) {
267 LOG(FATAL) << __func__
268 << ": Failed to find a previously traced event that matches the dispatched "
269 "event";
270 }
Prabir Pradhanac637022024-03-19 00:02:04 +0000271 tracer.mBackend->traceWindowDispatch(windowDispatchArgs, metadata);
Prabir Pradhan52ec3ff2024-02-22 03:26:38 +0000272 }
273 pendingDispatchArgs.clear();
274
Prabir Pradhane7701642024-02-22 04:06:53 +0000275 isEventProcessingComplete = true;
276}
277
Prabir Pradhana67623c2024-02-21 06:57:36 +0000278InputTracer::EventState::~EventState() {
279 if (isEventProcessingComplete) {
Prabir Pradhanbb7a0202024-02-10 02:09:01 +0000280 // This event has already been written to the trace as expected.
281 return;
282 }
Prabir Pradhan1ea04a32024-02-10 03:02:59 +0000283 // The event processing was never marked as complete, so do it now.
Prabir Pradhane7701642024-02-22 04:06:53 +0000284 // We should never end up here in normal operation. However, in tests, it's possible that we
285 // stop and destroy InputDispatcher without waiting for it to finish processing events, at
286 // which point an event (and thus its EventState) may be destroyed before processing finishes.
287 onEventProcessingComplete();
Prabir Pradhandae52792023-12-15 07:36:40 +0000288}
289
290} // namespace android::inputdispatcher::trace::impl