blob: 3b5a09694c6e0d7eb74ca7c9e886e3f5c47123fd [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>
22
23namespace android::inputdispatcher::trace::impl {
24
25namespace {
26
Prabir Pradhanbb7a0202024-02-10 02:09:01 +000027// Helper to std::visit with lambdas.
28template <typename... V>
29struct Visitor : V... {
30 using V::operator()...;
31};
32
Prabir Pradhandae52792023-12-15 07:36:40 +000033TracedEvent createTracedEvent(const MotionEntry& e) {
34 return TracedMotionEvent{e.id,
35 e.eventTime,
36 e.policyFlags,
37 e.deviceId,
38 e.source,
39 e.displayId,
40 e.action,
41 e.actionButton,
42 e.flags,
43 e.metaState,
44 e.buttonState,
45 e.classification,
46 e.edgeFlags,
47 e.xPrecision,
48 e.yPrecision,
49 e.xCursorPosition,
50 e.yCursorPosition,
51 e.downTime,
52 e.pointerProperties,
53 e.pointerCoords};
54}
55
56TracedEvent createTracedEvent(const KeyEntry& e) {
57 return TracedKeyEvent{e.id, e.eventTime, e.policyFlags, e.deviceId, e.source,
58 e.displayId, e.action, e.keyCode, e.scanCode, e.metaState,
59 e.downTime, e.flags, e.repeatCount};
60}
61
Prabir Pradhana67623c2024-02-21 06:57:36 +000062void writeEventToBackend(const TracedEvent& event, InputTracingBackendInterface& backend) {
63 std::visit(Visitor{[&](const TracedMotionEvent& e) { backend.traceMotionEvent(e); },
64 [&](const TracedKeyEvent& e) { backend.traceKeyEvent(e); }},
65 event);
66}
67
Prabir Pradhandae52792023-12-15 07:36:40 +000068} // namespace
69
70// --- InputTracer ---
71
72InputTracer::InputTracer(std::unique_ptr<InputTracingBackendInterface> backend)
Prabir Pradhanbb7a0202024-02-10 02:09:01 +000073 : mBackend(std::move(backend)) {}
Prabir Pradhandae52792023-12-15 07:36:40 +000074
75std::unique_ptr<EventTrackerInterface> InputTracer::traceInboundEvent(const EventEntry& entry) {
Prabir Pradhana67623c2024-02-21 06:57:36 +000076 // This is a newly traced inbound event. Create a new state to track it and its derived events.
77 auto eventState = std::make_shared<EventState>(*this);
Prabir Pradhandae52792023-12-15 07:36:40 +000078
79 if (entry.type == EventEntry::Type::MOTION) {
80 const auto& motion = static_cast<const MotionEntry&>(entry);
Prabir Pradhana67623c2024-02-21 06:57:36 +000081 eventState->events.emplace_back(createTracedEvent(motion));
Prabir Pradhandae52792023-12-15 07:36:40 +000082 } else if (entry.type == EventEntry::Type::KEY) {
83 const auto& key = static_cast<const KeyEntry&>(entry);
Prabir Pradhana67623c2024-02-21 06:57:36 +000084 eventState->events.emplace_back(createTracedEvent(key));
Prabir Pradhandae52792023-12-15 07:36:40 +000085 } else {
86 LOG(FATAL) << "Cannot trace EventEntry of type: " << ftl::enum_string(entry.type);
87 }
88
Prabir Pradhana67623c2024-02-21 06:57:36 +000089 return std::make_unique<EventTrackerImpl>(std::move(eventState), /*isDerived=*/false);
Prabir Pradhandae52792023-12-15 07:36:40 +000090}
91
92void InputTracer::dispatchToTargetHint(const EventTrackerInterface& cookie,
93 const InputTarget& target) {
Prabir Pradhana67623c2024-02-21 06:57:36 +000094 if (isDerivedCookie(cookie)) {
95 LOG(FATAL) << "Event target cannot be updated from a derived cookie.";
96 }
Prabir Pradhan1ea04a32024-02-10 03:02:59 +000097 auto& eventState = getState(cookie);
Prabir Pradhana67623c2024-02-21 06:57:36 +000098 if (eventState->isEventProcessingComplete) {
99 // TODO(b/210460522): Disallow adding new targets after eventProcessingComplete() is called.
100 return;
Prabir Pradhandae52792023-12-15 07:36:40 +0000101 }
102 // TODO(b/210460522): Determine if the event is sensitive based on the target.
103}
104
105void InputTracer::eventProcessingComplete(const EventTrackerInterface& cookie) {
Prabir Pradhana67623c2024-02-21 06:57:36 +0000106 if (isDerivedCookie(cookie)) {
107 LOG(FATAL) << "Event processing cannot be set from a derived cookie.";
108 }
Prabir Pradhan1ea04a32024-02-10 03:02:59 +0000109 auto& eventState = getState(cookie);
Prabir Pradhana67623c2024-02-21 06:57:36 +0000110 if (eventState->isEventProcessingComplete) {
Prabir Pradhanbb7a0202024-02-10 02:09:01 +0000111 LOG(FATAL) << "Traced event was already logged. "
112 "eventProcessingComplete() was likely called more than once.";
113 }
Prabir Pradhandae52792023-12-15 07:36:40 +0000114
Prabir Pradhana67623c2024-02-21 06:57:36 +0000115 for (const auto& event : eventState->events) {
116 writeEventToBackend(event, *mBackend);
117 }
118 eventState->isEventProcessingComplete = true;
119}
120
121std::unique_ptr<EventTrackerInterface> InputTracer::traceDerivedEvent(
122 const EventEntry& entry, const EventTrackerInterface& originalEventCookie) {
123 // This is an event derived from an already-established event. Use the same state to track
124 // this event too.
125 auto eventState = getState(originalEventCookie);
126
127 if (entry.type == EventEntry::Type::MOTION) {
128 const auto& motion = static_cast<const MotionEntry&>(entry);
129 eventState->events.emplace_back(createTracedEvent(motion));
130 } else if (entry.type == EventEntry::Type::KEY) {
131 const auto& key = static_cast<const KeyEntry&>(entry);
132 eventState->events.emplace_back(createTracedEvent(key));
133 } else {
134 LOG(FATAL) << "Cannot trace EventEntry of type: " << ftl::enum_string(entry.type);
135 }
136
137 if (eventState->isEventProcessingComplete) {
138 // It is possible for a derived event to be dispatched some time after the original event
139 // is dispatched, such as in the case of key fallback events. To account for these cases,
140 // derived events can be traced after the processing is complete for the original event.
141 writeEventToBackend(eventState->events.back(), *mBackend);
142 }
143 return std::make_unique<EventTrackerImpl>(std::move(eventState), /*isDerived=*/true);
Prabir Pradhandae52792023-12-15 07:36:40 +0000144}
145
146void InputTracer::traceEventDispatch(const DispatchEntry& dispatchEntry,
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000147 const EventTrackerInterface* cookie) {
Prabir Pradhanbb7a0202024-02-10 02:09:01 +0000148 const EventEntry& entry = *dispatchEntry.eventEntry;
Prabir Pradhan560d0d12024-03-07 18:08:27 +0000149 // TODO(b/328618922): Remove resolved key repeats after making repeatCount non-mutable.
150 // The KeyEntry's repeatCount is mutable and can be modified after an event is initially traced,
151 // so we need to find the repeatCount at the time of dispatching to trace it accurately.
152 int32_t resolvedKeyRepeatCount = 0;
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000153
Prabir Pradhanbb7a0202024-02-10 02:09:01 +0000154 TracedEvent traced;
155 if (entry.type == EventEntry::Type::MOTION) {
156 const auto& motion = static_cast<const MotionEntry&>(entry);
157 traced = createTracedEvent(motion);
158 } else if (entry.type == EventEntry::Type::KEY) {
159 const auto& key = static_cast<const KeyEntry&>(entry);
Prabir Pradhan560d0d12024-03-07 18:08:27 +0000160 resolvedKeyRepeatCount = key.repeatCount;
Prabir Pradhanbb7a0202024-02-10 02:09:01 +0000161 traced = createTracedEvent(key);
162 } else {
163 LOG(FATAL) << "Cannot trace EventEntry of type: " << ftl::enum_string(entry.type);
164 }
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000165
Prabir Pradhanbb7a0202024-02-10 02:09:01 +0000166 if (!cookie) {
167 // This event was not tracked as an inbound event, so trace it now.
Prabir Pradhana67623c2024-02-21 06:57:36 +0000168 writeEventToBackend(traced, *mBackend);
Prabir Pradhanbb7a0202024-02-10 02:09:01 +0000169 }
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000170
Prabir Pradhanbb7a0202024-02-10 02:09:01 +0000171 // The vsyncId only has meaning if the event is targeting a window.
172 const int32_t windowId = dispatchEntry.windowId.value_or(0);
173 const int32_t vsyncId = dispatchEntry.windowId.has_value() ? dispatchEntry.vsyncId : 0;
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000174
Prabir Pradhanbb7a0202024-02-10 02:09:01 +0000175 mBackend->traceWindowDispatch({std::move(traced), dispatchEntry.deliveryTime,
176 dispatchEntry.resolvedFlags, dispatchEntry.targetUid, vsyncId,
177 windowId, dispatchEntry.transform, dispatchEntry.rawTransform,
Prabir Pradhan560d0d12024-03-07 18:08:27 +0000178 /*hmac=*/{}, resolvedKeyRepeatCount});
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000179}
Prabir Pradhandae52792023-12-15 07:36:40 +0000180
Prabir Pradhana67623c2024-02-21 06:57:36 +0000181std::shared_ptr<InputTracer::EventState>& InputTracer::getState(
182 const EventTrackerInterface& cookie) {
Prabir Pradhanbb7a0202024-02-10 02:09:01 +0000183 return static_cast<const EventTrackerImpl&>(cookie).mState;
Prabir Pradhandae52792023-12-15 07:36:40 +0000184}
185
Prabir Pradhana67623c2024-02-21 06:57:36 +0000186bool InputTracer::isDerivedCookie(const EventTrackerInterface& cookie) {
187 return static_cast<const EventTrackerImpl&>(cookie).mIsDerived;
188}
Prabir Pradhandae52792023-12-15 07:36:40 +0000189
Prabir Pradhana67623c2024-02-21 06:57:36 +0000190// --- InputTracer::EventState ---
Prabir Pradhandae52792023-12-15 07:36:40 +0000191
Prabir Pradhana67623c2024-02-21 06:57:36 +0000192InputTracer::EventState::~EventState() {
193 if (isEventProcessingComplete) {
Prabir Pradhanbb7a0202024-02-10 02:09:01 +0000194 // This event has already been written to the trace as expected.
195 return;
196 }
Prabir Pradhan1ea04a32024-02-10 03:02:59 +0000197 // The event processing was never marked as complete, so do it now.
Prabir Pradhanbb7a0202024-02-10 02:09:01 +0000198 // TODO(b/210460522): Determine why/where the event is being destroyed before
199 // eventProcessingComplete() is called.
Prabir Pradhana67623c2024-02-21 06:57:36 +0000200 for (const auto& event : events) {
201 writeEventToBackend(event, *tracer.mBackend);
202 }
203 isEventProcessingComplete = true;
Prabir Pradhandae52792023-12-15 07:36:40 +0000204}
205
206} // namespace android::inputdispatcher::trace::impl