1 /*
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>
22 #include <private/android_filesystem_config.h>
23 
24 namespace android::inputdispatcher::trace::impl {
25 
26 namespace {
27 
28 // Helper to std::visit with lambdas.
29 template <typename... V>
30 struct Visitor : V... {
31     using V::operator()...;
32 };
33 
createTracedEvent(const MotionEntry & e,EventType type)34 TracedEvent createTracedEvent(const MotionEntry& e, EventType type) {
35     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,
54                              e.pointerCoords,
55                              type};
56 }
57 
createTracedEvent(const KeyEntry & e,EventType type)58 TracedEvent createTracedEvent(const KeyEntry& e, EventType type) {
59     return TracedKeyEvent{e.id,        e.eventTime, e.policyFlags, e.deviceId, e.source,
60                           e.displayId, e.action,    e.keyCode,     e.scanCode, e.metaState,
61                           e.downTime,  e.flags,     e.repeatCount, type};
62 }
63 
writeEventToBackend(const TracedEvent & event,const TracedEventMetadata metadata,InputTracingBackendInterface & backend)64 void writeEventToBackend(const TracedEvent& event, const TracedEventMetadata metadata,
65                          InputTracingBackendInterface& backend) {
66     std::visit(Visitor{[&](const TracedMotionEvent& e) { backend.traceMotionEvent(e, metadata); },
67                        [&](const TracedKeyEvent& e) { backend.traceKeyEvent(e, metadata); }},
68                event);
69 }
70 
getId(const trace::TracedEvent & v)71 inline auto getId(const trace::TracedEvent& v) {
72     return std::visit([](const auto& event) { return event.id; }, v);
73 }
74 
75 // Helper class to extract relevant information from InputTarget.
76 struct InputTargetInfo {
77     gui::Uid uid;
78     bool isSecureWindow;
79 };
80 
getTargetInfo(const InputTarget & target)81 InputTargetInfo 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     }
89     const auto& info = *target.windowHandle->getInfo();
90     const bool isSensitiveTarget =
91             info.inputConfig.test(gui::WindowInfo::InputConfig::SENSITIVE_FOR_PRIVACY);
92     return {target.windowHandle->getInfo()->ownerUid, isSensitiveTarget};
93 }
94 
95 } // namespace
96 
97 // --- InputTracer ---
98 
InputTracer(std::unique_ptr<InputTracingBackendInterface> backend)99 InputTracer::InputTracer(std::unique_ptr<InputTracingBackendInterface> backend)
100       : mBackend(std::move(backend)) {}
101 
traceInboundEvent(const EventEntry & entry)102 std::unique_ptr<EventTrackerInterface> InputTracer::traceInboundEvent(const EventEntry& entry) {
103     // This is a newly traced inbound event. Create a new state to track it and its derived events.
104     auto eventState = std::make_shared<EventState>(*this);
105 
106     if (entry.type == EventEntry::Type::MOTION) {
107         const auto& motion = static_cast<const MotionEntry&>(entry);
108         eventState->events.emplace_back(createTracedEvent(motion, EventType::INBOUND));
109     } else if (entry.type == EventEntry::Type::KEY) {
110         const auto& key = static_cast<const KeyEntry&>(entry);
111         eventState->events.emplace_back(createTracedEvent(key, EventType::INBOUND));
112     } else {
113         LOG(FATAL) << "Cannot trace EventEntry of type: " << ftl::enum_string(entry.type);
114     }
115 
116     return std::make_unique<EventTrackerImpl>(std::move(eventState), /*isDerived=*/false);
117 }
118 
createTrackerForSyntheticEvent()119 std::unique_ptr<EventTrackerInterface> InputTracer::createTrackerForSyntheticEvent() {
120     // Create a new EventState to track events derived from this tracker.
121     return std::make_unique<EventTrackerImpl>(std::make_shared<EventState>(*this),
122                                               /*isDerived=*/false);
123 }
124 
dispatchToTargetHint(const EventTrackerInterface & cookie,const InputTarget & target)125 void InputTracer::dispatchToTargetHint(const EventTrackerInterface& cookie,
126                                        const InputTarget& target) {
127     auto& eventState = getState(cookie);
128     const InputTargetInfo& targetInfo = getTargetInfo(target);
129     if (eventState->isEventProcessingComplete) {
130         // Disallow adding new targets after eventProcessingComplete() is called.
131         if (eventState->metadata.targets.count(targetInfo.uid) == 0) {
132             LOG(FATAL) << __func__ << ": Cannot add new target after eventProcessingComplete";
133         }
134         return;
135     }
136     if (isDerivedCookie(cookie)) {
137         // Disallow adding new targets from a derived cookie.
138         if (eventState->metadata.targets.count(targetInfo.uid) == 0) {
139             LOG(FATAL) << __func__ << ": Cannot add new target from a derived cookie";
140         }
141         return;
142     }
143 
144     eventState->metadata.targets.emplace(targetInfo.uid);
145     eventState->metadata.isSecure |= targetInfo.isSecureWindow;
146 }
147 
eventProcessingComplete(const EventTrackerInterface & cookie,nsecs_t processingTimestamp)148 void InputTracer::eventProcessingComplete(const EventTrackerInterface& cookie,
149                                           nsecs_t processingTimestamp) {
150     if (isDerivedCookie(cookie)) {
151         LOG(FATAL) << "Event processing cannot be set from a derived cookie.";
152     }
153     auto& eventState = getState(cookie);
154     if (eventState->isEventProcessingComplete) {
155         LOG(FATAL) << "Traced event was already logged. "
156                       "eventProcessingComplete() was likely called more than once.";
157     }
158     eventState->onEventProcessingComplete(processingTimestamp);
159 }
160 
traceDerivedEvent(const EventEntry & entry,const EventTrackerInterface & originalEventCookie)161 std::unique_ptr<EventTrackerInterface> InputTracer::traceDerivedEvent(
162         const EventEntry& entry, const EventTrackerInterface& originalEventCookie) {
163     // This is an event derived from an already-established event. Use the same state to track
164     // this event too.
165     auto eventState = getState(originalEventCookie);
166 
167     if (entry.type == EventEntry::Type::MOTION) {
168         const auto& motion = static_cast<const MotionEntry&>(entry);
169         eventState->events.emplace_back(createTracedEvent(motion, EventType::SYNTHESIZED));
170     } else if (entry.type == EventEntry::Type::KEY) {
171         const auto& key = static_cast<const KeyEntry&>(entry);
172         eventState->events.emplace_back(createTracedEvent(key, EventType::SYNTHESIZED));
173     } else {
174         LOG(FATAL) << "Cannot trace EventEntry of type: " << ftl::enum_string(entry.type);
175     }
176 
177     if (eventState->isEventProcessingComplete) {
178         // It is possible for a derived event to be dispatched some time after the original event
179         // is dispatched, such as in the case of key fallback events. To account for these cases,
180         // derived events can be traced after the processing is complete for the original event.
181         const auto& event = eventState->events.back();
182         writeEventToBackend(event, eventState->metadata, *mBackend);
183     }
184     return std::make_unique<EventTrackerImpl>(std::move(eventState), /*isDerived=*/true);
185 }
186 
traceEventDispatch(const DispatchEntry & dispatchEntry,const EventTrackerInterface & cookie)187 void InputTracer::traceEventDispatch(const DispatchEntry& dispatchEntry,
188                                      const EventTrackerInterface& cookie) {
189     auto& eventState = getState(cookie);
190     const EventEntry& entry = *dispatchEntry.eventEntry;
191     const int32_t eventId = entry.id;
192     // TODO(b/328618922): Remove resolved key repeats after making repeatCount non-mutable.
193     // The KeyEntry's repeatCount is mutable and can be modified after an event is initially traced,
194     // so we need to find the repeatCount at the time of dispatching to trace it accurately.
195     int32_t resolvedKeyRepeatCount = 0;
196     if (entry.type == EventEntry::Type::KEY) {
197         resolvedKeyRepeatCount = static_cast<const KeyEntry&>(entry).repeatCount;
198     }
199 
200     auto tracedEventIt =
201             std::find_if(eventState->events.begin(), eventState->events.end(),
202                          [eventId](const auto& event) { return eventId == getId(event); });
203     if (tracedEventIt == eventState->events.end()) {
204         LOG(FATAL)
205                 << __func__
206                 << ": Failed to find a previously traced event that matches the dispatched event";
207     }
208 
209     if (eventState->metadata.targets.count(dispatchEntry.targetUid) == 0) {
210         LOG(FATAL) << __func__ << ": Event is being dispatched to UID that it is not targeting";
211     }
212 
213     // The vsyncId only has meaning if the event is targeting a window.
214     const int32_t windowId = dispatchEntry.windowId.value_or(0);
215     const int32_t vsyncId = dispatchEntry.windowId.has_value() ? dispatchEntry.vsyncId : 0;
216 
217     // TODO(b/210460522): Pass HMAC into traceEventDispatch.
218     const WindowDispatchArgs windowDispatchArgs{*tracedEventIt,
219                                                 dispatchEntry.deliveryTime,
220                                                 dispatchEntry.resolvedFlags,
221                                                 dispatchEntry.targetUid,
222                                                 vsyncId,
223                                                 windowId,
224                                                 dispatchEntry.transform,
225                                                 dispatchEntry.rawTransform,
226                                                 /*hmac=*/{},
227                                                 resolvedKeyRepeatCount};
228     if (eventState->isEventProcessingComplete) {
229         mBackend->traceWindowDispatch(std::move(windowDispatchArgs), eventState->metadata);
230     } else {
231         eventState->pendingDispatchArgs.emplace_back(std::move(windowDispatchArgs));
232     }
233 }
234 
getState(const EventTrackerInterface & cookie)235 std::shared_ptr<InputTracer::EventState>& InputTracer::getState(
236         const EventTrackerInterface& cookie) {
237     return static_cast<const EventTrackerImpl&>(cookie).mState;
238 }
239 
isDerivedCookie(const EventTrackerInterface & cookie)240 bool InputTracer::isDerivedCookie(const EventTrackerInterface& cookie) {
241     return static_cast<const EventTrackerImpl&>(cookie).mIsDerived;
242 }
243 
244 // --- InputTracer::EventState ---
245 
onEventProcessingComplete(nsecs_t processingTimestamp)246 void InputTracer::EventState::onEventProcessingComplete(nsecs_t processingTimestamp) {
247     metadata.processingTimestamp = processingTimestamp;
248     metadata.isImeConnectionActive = tracer.mIsImeConnectionActive;
249 
250     // Write all of the events known so far to the trace.
251     for (const auto& event : events) {
252         writeEventToBackend(event, metadata, *tracer.mBackend);
253     }
254     // Write all pending dispatch args to the trace.
255     for (const auto& windowDispatchArgs : pendingDispatchArgs) {
256         auto tracedEventIt =
257                 std::find_if(events.begin(), events.end(),
258                              [id = getId(windowDispatchArgs.eventEntry)](const auto& event) {
259                                  return id == getId(event);
260                              });
261         if (tracedEventIt == events.end()) {
262             LOG(FATAL) << __func__
263                        << ": Failed to find a previously traced event that matches the dispatched "
264                           "event";
265         }
266         tracer.mBackend->traceWindowDispatch(windowDispatchArgs, metadata);
267     }
268     pendingDispatchArgs.clear();
269 
270     isEventProcessingComplete = true;
271 }
272 
~EventState()273 InputTracer::EventState::~EventState() {
274     if (isEventProcessingComplete) {
275         // This event has already been written to the trace as expected.
276         return;
277     }
278     // The event processing was never marked as complete, so do it now.
279     // We should never end up here in normal operation. However, in tests, it's possible that we
280     // stop and destroy InputDispatcher without waiting for it to finish processing events, at
281     // which point an event (and thus its EventState) may be destroyed before processing finishes.
282     onEventProcessingComplete(systemTime(CLOCK_MONOTONIC));
283 }
284 
285 } // namespace android::inputdispatcher::trace::impl
286