blob: b76bec31b69346a220ef82a4d56b42a235a3c114 [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 "InputTracingPerfettoBackend.h"
20
21#include "AndroidInputEventProtoConverter.h"
22
23#include <android-base/logging.h>
24#include <perfetto/trace/android/android_input_event.pbzero.h>
Prabir Pradhanbf3c8322024-02-23 02:38:36 +000025#include <private/android_filesystem_config.h>
Prabir Pradhandae52792023-12-15 07:36:40 +000026
27namespace android::inputdispatcher::trace::impl {
28
29namespace {
30
31constexpr auto INPUT_EVENT_TRACE_DATA_SOURCE_NAME = "android.input.inputevent";
32
Prabir Pradhanbf3c8322024-02-23 02:38:36 +000033bool isPermanentlyAllowed(gui::Uid uid) {
34 switch (uid.val()) {
35 case AID_SYSTEM:
36 case AID_SHELL:
37 case AID_ROOT:
38 return true;
39 default:
40 return false;
41 }
42}
43
Prabir Pradhandae52792023-12-15 07:36:40 +000044} // namespace
45
46// --- PerfettoBackend::InputEventDataSource ---
47
Prabir Pradhan58f19f62024-03-07 21:54:34 +000048PerfettoBackend::InputEventDataSource::InputEventDataSource() : mInstanceId(sNextInstanceId++) {}
49
50void PerfettoBackend::InputEventDataSource::OnSetup(const InputEventDataSource::SetupArgs& args) {
51 LOG(INFO) << "Setting up perfetto trace for: " << INPUT_EVENT_TRACE_DATA_SOURCE_NAME
52 << ", instanceId: " << mInstanceId;
53 const auto rawConfig = args.config->android_input_event_config_raw();
54 auto protoConfig = perfetto::protos::pbzero::AndroidInputEventConfig::Decoder{rawConfig};
55
56 mConfig = AndroidInputEventProtoConverter::parseConfig(protoConfig);
Prabir Pradhandae52792023-12-15 07:36:40 +000057}
58
Prabir Pradhan58f19f62024-03-07 21:54:34 +000059void PerfettoBackend::InputEventDataSource::OnStart(const InputEventDataSource::StartArgs&) {
60 LOG(INFO) << "Starting perfetto trace for: " << INPUT_EVENT_TRACE_DATA_SOURCE_NAME
61 << ", instanceId: " << mInstanceId;
62}
63
64void PerfettoBackend::InputEventDataSource::OnStop(const InputEventDataSource::StopArgs&) {
65 LOG(INFO) << "Stopping perfetto trace for: " << INPUT_EVENT_TRACE_DATA_SOURCE_NAME
66 << ", instanceId: " << mInstanceId;
Prabir Pradhandae52792023-12-15 07:36:40 +000067 InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) { ctx.Flush(); });
68}
69
Prabir Pradhanbf3c8322024-02-23 02:38:36 +000070void PerfettoBackend::InputEventDataSource::initializeUidMap(GetPackageUid getPackageUid) {
71 if (mUidMap.has_value()) {
72 return;
73 }
74
75 mUidMap = {{}};
76 for (const auto& rule : mConfig.rules) {
77 for (const auto& package : rule.matchAllPackages) {
78 mUidMap->emplace(package, getPackageUid(package));
79 }
80 for (const auto& package : rule.matchAnyPackages) {
81 mUidMap->emplace(package, getPackageUid(package));
82 }
83 }
84}
85
Prabir Pradhan4c49aad2024-02-08 20:42:35 +000086bool PerfettoBackend::InputEventDataSource::shouldIgnoreTracedInputEvent(
87 const EventType& type) const {
88 if (!getFlags().test(TraceFlag::TRACE_DISPATCHER_INPUT_EVENTS)) {
89 // Ignore all input events.
90 return true;
91 }
92 if (!getFlags().test(TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH) &&
93 type != EventType::INBOUND) {
94 // When window dispatch tracing is disabled, ignore any events that are not inbound events.
95 return true;
96 }
97 return false;
98}
99
Prabir Pradhanb5682382024-02-23 22:52:31 +0000100TraceLevel PerfettoBackend::InputEventDataSource::resolveTraceLevel(
101 const TracedEventArgs& args) const {
102 // Check for matches with the rules in the order that they are defined.
103 for (const auto& rule : mConfig.rules) {
104 if (ruleMatches(rule, args)) {
105 return rule.level;
106 }
107 }
Prabir Pradhanb5682382024-02-23 22:52:31 +0000108 // The event is not traced if it matched zero rules.
109 return TraceLevel::TRACE_LEVEL_NONE;
110}
111
112bool PerfettoBackend::InputEventDataSource::ruleMatches(const TraceRule& rule,
113 const TracedEventArgs& args) const {
114 // By default, a rule will match all events. Return early if the rule does not match.
115
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000116 // Match the event if it is directed to a secure window.
Prabir Pradhanb5682382024-02-23 22:52:31 +0000117 if (rule.matchSecure.has_value() && *rule.matchSecure != args.isSecure) {
118 return false;
119 }
120
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000121 // Match the event if all of its target packages are explicitly allowed in the "match all" list.
122 if (!rule.matchAllPackages.empty() &&
123 !std::all_of(args.targets.begin(), args.targets.end(), [&](const auto& uid) {
124 return isPermanentlyAllowed(uid) ||
125 std::any_of(rule.matchAllPackages.begin(), rule.matchAllPackages.end(),
126 [&](const auto& pkg) { return uid == mUidMap->at(pkg); });
127 })) {
128 return false;
129 }
130
131 // Match the event if any of its target packages are allowed in the "match any" list.
132 if (!rule.matchAnyPackages.empty() &&
133 !std::any_of(args.targets.begin(), args.targets.end(), [&](const auto& uid) {
134 return std::any_of(rule.matchAnyPackages.begin(), rule.matchAnyPackages.end(),
135 [&](const auto& pkg) { return uid == mUidMap->at(pkg); });
136 })) {
137 return false;
138 }
139
140 // The event matches all matchers specified in the rule.
Prabir Pradhanb5682382024-02-23 22:52:31 +0000141 return true;
142}
143
Prabir Pradhandae52792023-12-15 07:36:40 +0000144// --- PerfettoBackend ---
145
146std::once_flag PerfettoBackend::sDataSourceRegistrationFlag{};
147
Prabir Pradhan58f19f62024-03-07 21:54:34 +0000148std::atomic<int32_t> PerfettoBackend::sNextInstanceId{1};
149
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000150PerfettoBackend::PerfettoBackend(GetPackageUid getPackagesForUid)
151 : mGetPackageUid(getPackagesForUid) {
Prabir Pradhandae52792023-12-15 07:36:40 +0000152 // Use a once-flag to ensure that the data source is only registered once per boot, since
153 // we never unregister the InputEventDataSource.
154 std::call_once(sDataSourceRegistrationFlag, []() {
155 perfetto::TracingInitArgs args;
156 args.backends = perfetto::kSystemBackend;
157 perfetto::Tracing::Initialize(args);
158
159 // Register our custom data source for input event tracing.
160 perfetto::DataSourceDescriptor dsd;
161 dsd.set_name(INPUT_EVENT_TRACE_DATA_SOURCE_NAME);
162 InputEventDataSource::Register(dsd);
163 LOG(INFO) << "InputTracer initialized for data source: "
164 << INPUT_EVENT_TRACE_DATA_SOURCE_NAME;
165 });
166}
167
Prabir Pradhan8c3b1432024-02-09 23:34:16 +0000168void PerfettoBackend::traceMotionEvent(const TracedMotionEvent& event,
169 const TracedEventArgs& args) {
Prabir Pradhandae52792023-12-15 07:36:40 +0000170 InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000171 auto dataSource = ctx.GetDataSourceLocked();
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000172 dataSource->initializeUidMap(mGetPackageUid);
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000173 if (dataSource->shouldIgnoreTracedInputEvent(event.eventType)) {
174 return;
175 }
Prabir Pradhanb5682382024-02-23 22:52:31 +0000176 const TraceLevel traceLevel = dataSource->resolveTraceLevel(args);
177 if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) {
178 return;
179 }
180 const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED;
Prabir Pradhandae52792023-12-15 07:36:40 +0000181 auto tracePacket = ctx.NewTracePacket();
182 auto* inputEvent = tracePacket->set_android_input_event();
Prabir Pradhanb5682382024-02-23 22:52:31 +0000183 auto* dispatchMotion = isRedacted ? inputEvent->set_dispatcher_motion_event_redacted()
184 : inputEvent->set_dispatcher_motion_event();
185 AndroidInputEventProtoConverter::toProtoMotionEvent(event, *dispatchMotion, isRedacted);
Prabir Pradhandae52792023-12-15 07:36:40 +0000186 });
187}
188
Prabir Pradhan8c3b1432024-02-09 23:34:16 +0000189void PerfettoBackend::traceKeyEvent(const TracedKeyEvent& event, const TracedEventArgs& args) {
Prabir Pradhandae52792023-12-15 07:36:40 +0000190 InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000191 auto dataSource = ctx.GetDataSourceLocked();
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000192 dataSource->initializeUidMap(mGetPackageUid);
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000193 if (dataSource->shouldIgnoreTracedInputEvent(event.eventType)) {
194 return;
195 }
Prabir Pradhanb5682382024-02-23 22:52:31 +0000196 const TraceLevel traceLevel = dataSource->resolveTraceLevel(args);
197 if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) {
198 return;
199 }
200 const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED;
Prabir Pradhandae52792023-12-15 07:36:40 +0000201 auto tracePacket = ctx.NewTracePacket();
202 auto* inputEvent = tracePacket->set_android_input_event();
Prabir Pradhanb5682382024-02-23 22:52:31 +0000203 auto* dispatchKey = isRedacted ? inputEvent->set_dispatcher_key_event_redacted()
204 : inputEvent->set_dispatcher_key_event();
205 AndroidInputEventProtoConverter::toProtoKeyEvent(event, *dispatchKey, isRedacted);
Prabir Pradhandae52792023-12-15 07:36:40 +0000206 });
207}
208
Prabir Pradhan8c3b1432024-02-09 23:34:16 +0000209void PerfettoBackend::traceWindowDispatch(const WindowDispatchArgs& dispatchArgs,
210 const TracedEventArgs& args) {
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000211 InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000212 auto dataSource = ctx.GetDataSourceLocked();
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000213 dataSource->initializeUidMap(mGetPackageUid);
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000214 if (!dataSource->getFlags().test(TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH)) {
215 return;
216 }
Prabir Pradhanb5682382024-02-23 22:52:31 +0000217 const TraceLevel traceLevel = dataSource->resolveTraceLevel(args);
218 if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) {
219 return;
220 }
221 const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED;
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000222 auto tracePacket = ctx.NewTracePacket();
Prabir Pradhan8c3b1432024-02-09 23:34:16 +0000223 auto* inputEvent = tracePacket->set_android_input_event();
Prabir Pradhanb5682382024-02-23 22:52:31 +0000224 auto* dispatchEvent = isRedacted
225 ? inputEvent->set_dispatcher_window_dispatch_event_redacted()
226 : inputEvent->set_dispatcher_window_dispatch_event();
227 AndroidInputEventProtoConverter::toProtoWindowDispatchEvent(dispatchArgs, *dispatchEvent,
228 isRedacted);
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000229 });
Prabir Pradhandae52792023-12-15 07:36:40 +0000230}
231
232} // namespace android::inputdispatcher::trace::impl