blob: 91ebe9bb5f90e2eb6d315d08c4f4254268cab4fa [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(
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000101 const TracedEventMetadata& metadata) const {
Prabir Pradhanb5682382024-02-23 22:52:31 +0000102 // Check for matches with the rules in the order that they are defined.
103 for (const auto& rule : mConfig.rules) {
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000104 if (ruleMatches(rule, metadata)) {
Prabir Pradhanb5682382024-02-23 22:52:31 +0000105 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,
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000113 const TracedEventMetadata& metadata) const {
Prabir Pradhanb5682382024-02-23 22:52:31 +0000114 // 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 Pradhanc7edaaa2024-03-15 15:31:02 +0000117 if (rule.matchSecure.has_value() && *rule.matchSecure != metadata.isSecure) {
Prabir Pradhanb5682382024-02-23 22:52:31 +0000118 return false;
119 }
120
Prabir Pradhan04a66422024-03-15 22:45:27 +0000121 // Match the event if it was processed while there was an active InputMethod connection.
122 if (rule.matchImeConnectionActive.has_value() &&
123 *rule.matchImeConnectionActive != metadata.isImeConnectionActive) {
124 return false;
125 }
126
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000127 // Match the event if all of its target packages are explicitly allowed in the "match all" list.
128 if (!rule.matchAllPackages.empty() &&
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000129 !std::all_of(metadata.targets.begin(), metadata.targets.end(), [&](const auto& uid) {
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000130 return isPermanentlyAllowed(uid) ||
131 std::any_of(rule.matchAllPackages.begin(), rule.matchAllPackages.end(),
132 [&](const auto& pkg) { return uid == mUidMap->at(pkg); });
133 })) {
134 return false;
135 }
136
137 // Match the event if any of its target packages are allowed in the "match any" list.
138 if (!rule.matchAnyPackages.empty() &&
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000139 !std::any_of(metadata.targets.begin(), metadata.targets.end(), [&](const auto& uid) {
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000140 return std::any_of(rule.matchAnyPackages.begin(), rule.matchAnyPackages.end(),
141 [&](const auto& pkg) { return uid == mUidMap->at(pkg); });
142 })) {
143 return false;
144 }
145
146 // The event matches all matchers specified in the rule.
Prabir Pradhanb5682382024-02-23 22:52:31 +0000147 return true;
148}
149
Prabir Pradhandae52792023-12-15 07:36:40 +0000150// --- PerfettoBackend ---
151
Prabir Pradhan9a9897d2024-03-21 21:52:57 +0000152bool PerfettoBackend::sUseInProcessBackendForTest{false};
153
Prabir Pradhandae52792023-12-15 07:36:40 +0000154std::once_flag PerfettoBackend::sDataSourceRegistrationFlag{};
155
Prabir Pradhan58f19f62024-03-07 21:54:34 +0000156std::atomic<int32_t> PerfettoBackend::sNextInstanceId{1};
157
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000158PerfettoBackend::PerfettoBackend(GetPackageUid getPackagesForUid)
159 : mGetPackageUid(getPackagesForUid) {
Prabir Pradhandae52792023-12-15 07:36:40 +0000160 // Use a once-flag to ensure that the data source is only registered once per boot, since
161 // we never unregister the InputEventDataSource.
162 std::call_once(sDataSourceRegistrationFlag, []() {
163 perfetto::TracingInitArgs args;
Prabir Pradhan9a9897d2024-03-21 21:52:57 +0000164 args.backends = sUseInProcessBackendForTest ? perfetto::kInProcessBackend
165 : perfetto::kSystemBackend;
Prabir Pradhandae52792023-12-15 07:36:40 +0000166 perfetto::Tracing::Initialize(args);
167
168 // Register our custom data source for input event tracing.
169 perfetto::DataSourceDescriptor dsd;
170 dsd.set_name(INPUT_EVENT_TRACE_DATA_SOURCE_NAME);
171 InputEventDataSource::Register(dsd);
172 LOG(INFO) << "InputTracer initialized for data source: "
173 << INPUT_EVENT_TRACE_DATA_SOURCE_NAME;
174 });
175}
176
Prabir Pradhan8c3b1432024-02-09 23:34:16 +0000177void PerfettoBackend::traceMotionEvent(const TracedMotionEvent& event,
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000178 const TracedEventMetadata& metadata) {
Prabir Pradhandae52792023-12-15 07:36:40 +0000179 InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000180 auto dataSource = ctx.GetDataSourceLocked();
Prabir Pradhan9a9897d2024-03-21 21:52:57 +0000181 if (!dataSource.valid()) {
182 return;
183 }
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000184 dataSource->initializeUidMap(mGetPackageUid);
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000185 if (dataSource->shouldIgnoreTracedInputEvent(event.eventType)) {
186 return;
187 }
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000188 const TraceLevel traceLevel = dataSource->resolveTraceLevel(metadata);
Prabir Pradhanb5682382024-02-23 22:52:31 +0000189 if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) {
190 return;
191 }
192 const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED;
Prabir Pradhandae52792023-12-15 07:36:40 +0000193 auto tracePacket = ctx.NewTracePacket();
194 auto* inputEvent = tracePacket->set_android_input_event();
Prabir Pradhanb5682382024-02-23 22:52:31 +0000195 auto* dispatchMotion = isRedacted ? inputEvent->set_dispatcher_motion_event_redacted()
196 : inputEvent->set_dispatcher_motion_event();
197 AndroidInputEventProtoConverter::toProtoMotionEvent(event, *dispatchMotion, isRedacted);
Prabir Pradhandae52792023-12-15 07:36:40 +0000198 });
199}
200
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000201void PerfettoBackend::traceKeyEvent(const TracedKeyEvent& event,
202 const TracedEventMetadata& metadata) {
Prabir Pradhandae52792023-12-15 07:36:40 +0000203 InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000204 auto dataSource = ctx.GetDataSourceLocked();
Prabir Pradhan9a9897d2024-03-21 21:52:57 +0000205 if (!dataSource.valid()) {
206 return;
207 }
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000208 dataSource->initializeUidMap(mGetPackageUid);
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000209 if (dataSource->shouldIgnoreTracedInputEvent(event.eventType)) {
210 return;
211 }
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000212 const TraceLevel traceLevel = dataSource->resolveTraceLevel(metadata);
Prabir Pradhanb5682382024-02-23 22:52:31 +0000213 if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) {
214 return;
215 }
216 const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED;
Prabir Pradhandae52792023-12-15 07:36:40 +0000217 auto tracePacket = ctx.NewTracePacket();
218 auto* inputEvent = tracePacket->set_android_input_event();
Prabir Pradhanb5682382024-02-23 22:52:31 +0000219 auto* dispatchKey = isRedacted ? inputEvent->set_dispatcher_key_event_redacted()
220 : inputEvent->set_dispatcher_key_event();
221 AndroidInputEventProtoConverter::toProtoKeyEvent(event, *dispatchKey, isRedacted);
Prabir Pradhandae52792023-12-15 07:36:40 +0000222 });
223}
224
Prabir Pradhan8c3b1432024-02-09 23:34:16 +0000225void PerfettoBackend::traceWindowDispatch(const WindowDispatchArgs& dispatchArgs,
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000226 const TracedEventMetadata& metadata) {
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000227 InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000228 auto dataSource = ctx.GetDataSourceLocked();
Prabir Pradhan9a9897d2024-03-21 21:52:57 +0000229 if (!dataSource.valid()) {
230 return;
231 }
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000232 dataSource->initializeUidMap(mGetPackageUid);
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000233 if (!dataSource->getFlags().test(TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH)) {
234 return;
235 }
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000236 const TraceLevel traceLevel = dataSource->resolveTraceLevel(metadata);
Prabir Pradhanb5682382024-02-23 22:52:31 +0000237 if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) {
238 return;
239 }
240 const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED;
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000241 auto tracePacket = ctx.NewTracePacket();
Prabir Pradhan8c3b1432024-02-09 23:34:16 +0000242 auto* inputEvent = tracePacket->set_android_input_event();
Prabir Pradhanb5682382024-02-23 22:52:31 +0000243 auto* dispatchEvent = isRedacted
244 ? inputEvent->set_dispatcher_window_dispatch_event_redacted()
245 : inputEvent->set_dispatcher_window_dispatch_event();
246 AndroidInputEventProtoConverter::toProtoWindowDispatchEvent(dispatchArgs, *dispatchEvent,
247 isRedacted);
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000248 });
Prabir Pradhandae52792023-12-15 07:36:40 +0000249}
250
251} // namespace android::inputdispatcher::trace::impl