blob: 8a855c2035e7baccceeb5b600d972a7d8b32adc8 [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 Pradhanadc59b42023-12-15 05:34:11 +000022#include <utils/AndroidThreads.h>
Prabir Pradhandae52792023-12-15 07:36:40 +000023
24namespace android::inputdispatcher::trace::impl {
25
26namespace {
27
28TracedEvent createTracedEvent(const MotionEntry& e) {
29 return TracedMotionEvent{e.id,
30 e.eventTime,
31 e.policyFlags,
32 e.deviceId,
33 e.source,
34 e.displayId,
35 e.action,
36 e.actionButton,
37 e.flags,
38 e.metaState,
39 e.buttonState,
40 e.classification,
41 e.edgeFlags,
42 e.xPrecision,
43 e.yPrecision,
44 e.xCursorPosition,
45 e.yCursorPosition,
46 e.downTime,
47 e.pointerProperties,
48 e.pointerCoords};
49}
50
51TracedEvent createTracedEvent(const KeyEntry& e) {
52 return TracedKeyEvent{e.id, e.eventTime, e.policyFlags, e.deviceId, e.source,
53 e.displayId, e.action, e.keyCode, e.scanCode, e.metaState,
54 e.downTime, e.flags, e.repeatCount};
55}
56
57} // namespace
58
59// --- InputTracer ---
60
61InputTracer::InputTracer(std::unique_ptr<InputTracingBackendInterface> backend)
62 : mTracerThread(&InputTracer::threadLoop, this), mBackend(std::move(backend)) {}
63
64InputTracer::~InputTracer() {
65 {
66 std::scoped_lock lock(mLock);
67 mThreadExit = true;
68 }
69 mThreadWakeCondition.notify_all();
70 mTracerThread.join();
71}
72
73std::unique_ptr<EventTrackerInterface> InputTracer::traceInboundEvent(const EventEntry& entry) {
74 std::scoped_lock lock(mLock);
75 TracedEvent traced;
76
77 if (entry.type == EventEntry::Type::MOTION) {
78 const auto& motion = static_cast<const MotionEntry&>(entry);
79 traced = createTracedEvent(motion);
80 } else if (entry.type == EventEntry::Type::KEY) {
81 const auto& key = static_cast<const KeyEntry&>(entry);
82 traced = createTracedEvent(key);
83 } else {
84 LOG(FATAL) << "Cannot trace EventEntry of type: " << ftl::enum_string(entry.type);
85 }
86
87 return std::make_unique<EventTrackerImpl>(*this, std::move(traced));
88}
89
90void InputTracer::dispatchToTargetHint(const EventTrackerInterface& cookie,
91 const InputTarget& target) {
92 std::scoped_lock lock(mLock);
93 auto& cookieState = getState(cookie);
94 if (!cookieState) {
95 LOG(FATAL) << "dispatchToTargetHint() should not be called after eventProcessingComplete()";
96 }
97 // TODO(b/210460522): Determine if the event is sensitive based on the target.
98}
99
100void InputTracer::eventProcessingComplete(const EventTrackerInterface& cookie) {
101 {
102 std::scoped_lock lock(mLock);
103 auto& cookieState = getState(cookie);
104 if (!cookieState) {
105 LOG(FATAL) << "Traced event was already logged. "
106 "eventProcessingComplete() was likely called more than once.";
107 }
108 mTraceQueue.emplace_back(std::move(*cookieState));
109 cookieState.reset();
110 } // release lock
111
112 mThreadWakeCondition.notify_all();
113}
114
115void InputTracer::traceEventDispatch(const DispatchEntry& dispatchEntry,
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000116 const EventTrackerInterface* cookie) {
117 {
118 std::scoped_lock lock(mLock);
119 const EventEntry& entry = *dispatchEntry.eventEntry;
120
121 TracedEvent traced;
122 if (entry.type == EventEntry::Type::MOTION) {
123 const auto& motion = static_cast<const MotionEntry&>(entry);
124 traced = createTracedEvent(motion);
125 } else if (entry.type == EventEntry::Type::KEY) {
126 const auto& key = static_cast<const KeyEntry&>(entry);
127 traced = createTracedEvent(key);
128 } else {
129 LOG(FATAL) << "Cannot trace EventEntry of type: " << ftl::enum_string(entry.type);
130 }
131
132 if (!cookie) {
133 // This event was not tracked as an inbound event, so trace it now.
134 mTraceQueue.emplace_back(traced);
135 }
136
137 // The vsyncId only has meaning if the event is targeting a window.
138 const int32_t windowId = dispatchEntry.windowId.value_or(0);
139 const int32_t vsyncId = dispatchEntry.windowId.has_value() ? dispatchEntry.vsyncId : 0;
140
141 mDispatchTraceQueue.emplace_back(std::move(traced), dispatchEntry.deliveryTime,
142 dispatchEntry.resolvedFlags, dispatchEntry.targetUid,
143 vsyncId, windowId, dispatchEntry.transform,
144 dispatchEntry.rawTransform);
145 } // release lock
146
147 mThreadWakeCondition.notify_all();
148}
Prabir Pradhandae52792023-12-15 07:36:40 +0000149
150std::optional<InputTracer::EventState>& InputTracer::getState(const EventTrackerInterface& cookie) {
151 return static_cast<const EventTrackerImpl&>(cookie).mLockedState;
152}
153
154void InputTracer::threadLoop() {
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000155 androidSetThreadName("InputTracer");
156
Prabir Pradhan73ba9202024-02-05 22:55:46 +0000157 std::vector<const EventState> eventsToTrace;
158 std::vector<const WindowDispatchArgs> dispatchEventsToTrace;
159
Prabir Pradhandae52792023-12-15 07:36:40 +0000160 while (true) {
Prabir Pradhan73ba9202024-02-05 22:55:46 +0000161 { // acquire lock
Prabir Pradhandae52792023-12-15 07:36:40 +0000162 std::unique_lock lock(mLock);
163 base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhan73ba9202024-02-05 22:55:46 +0000164
165 // Wait until we need to process more events or exit.
166 mThreadWakeCondition.wait(lock, [&]() REQUIRES(mLock) {
167 return mThreadExit || !mTraceQueue.empty() || !mDispatchTraceQueue.empty();
168 });
Prabir Pradhandae52792023-12-15 07:36:40 +0000169 if (mThreadExit) {
170 return;
171 }
Prabir Pradhandae52792023-12-15 07:36:40 +0000172
173 mTraceQueue.swap(eventsToTrace);
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000174 mDispatchTraceQueue.swap(dispatchEventsToTrace);
Prabir Pradhandae52792023-12-15 07:36:40 +0000175 } // release lock
176
177 // Trace the events into the backend without holding the lock to reduce the amount of
178 // work performed in the critical section.
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000179 writeEventsToBackend(eventsToTrace, dispatchEventsToTrace);
Prabir Pradhandae52792023-12-15 07:36:40 +0000180 eventsToTrace.clear();
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000181 dispatchEventsToTrace.clear();
Prabir Pradhandae52792023-12-15 07:36:40 +0000182 }
183}
184
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000185void InputTracer::writeEventsToBackend(
186 const std::vector<const EventState>& events,
187 const std::vector<const WindowDispatchArgs>& dispatchEvents) {
Prabir Pradhandae52792023-12-15 07:36:40 +0000188 for (const auto& event : events) {
189 if (auto* motion = std::get_if<TracedMotionEvent>(&event.event); motion != nullptr) {
190 mBackend->traceMotionEvent(*motion);
191 } else {
192 mBackend->traceKeyEvent(std::get<TracedKeyEvent>(event.event));
193 }
194 }
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000195
196 for (const auto& dispatchArgs : dispatchEvents) {
197 mBackend->traceWindowDispatch(dispatchArgs);
198 }
Prabir Pradhandae52792023-12-15 07:36:40 +0000199}
200
201// --- InputTracer::EventTrackerImpl ---
202
203InputTracer::EventTrackerImpl::EventTrackerImpl(InputTracer& tracer, TracedEvent&& event)
204 : mTracer(tracer), mLockedState(event) {}
205
206InputTracer::EventTrackerImpl::~EventTrackerImpl() {
207 {
208 std::scoped_lock lock(mTracer.mLock);
209 if (!mLockedState) {
210 // This event has already been written to the trace as expected.
211 return;
212 }
213 // We're still holding on to the state, which means it hasn't yet been written to the trace.
214 // Write it to the trace now.
215 // TODO(b/210460522): Determine why/where the event is being destroyed before
216 // eventProcessingComplete() is called.
217 mTracer.mTraceQueue.emplace_back(std::move(*mLockedState));
218 mLockedState.reset();
219 } // release lock
220
221 mTracer.mThreadWakeCondition.notify_all();
222}
223
224} // namespace android::inputdispatcher::trace::impl