blob: 77b5c2ebcd0d09a4871522ec5e808ddc17868aaa [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>
Prabir Pradhanf4099452024-04-12 18:34:14 +000024#include <binder/IServiceManager.h>
Prabir Pradhandae52792023-12-15 07:36:40 +000025#include <perfetto/trace/android/android_input_event.pbzero.h>
Prabir Pradhan6ef947a2024-06-10 20:00:51 +000026#include <perfetto/trace/android/winscope_extensions.pbzero.h>
27#include <perfetto/trace/android/winscope_extensions_impl.pbzero.h>
Prabir Pradhanbf3c8322024-02-23 02:38:36 +000028#include <private/android_filesystem_config.h>
Prabir Pradhanf4099452024-04-12 18:34:14 +000029#include <utils/String16.h>
Prabir Pradhandae52792023-12-15 07:36:40 +000030
31namespace android::inputdispatcher::trace::impl {
32
33namespace {
34
35constexpr auto INPUT_EVENT_TRACE_DATA_SOURCE_NAME = "android.input.inputevent";
36
Prabir Pradhanbf3c8322024-02-23 02:38:36 +000037bool isPermanentlyAllowed(gui::Uid uid) {
38 switch (uid.val()) {
39 case AID_SYSTEM:
40 case AID_SHELL:
41 case AID_ROOT:
42 return true;
43 default:
44 return false;
45 }
46}
47
Prabir Pradhanf4099452024-04-12 18:34:14 +000048sp<content::pm::IPackageManagerNative> getPackageManager() {
49 sp<IServiceManager> serviceManager = defaultServiceManager();
50 if (!serviceManager) {
51 LOG(ERROR) << __func__ << ": unable to access native ServiceManager";
52 return nullptr;
53 }
54
55 sp<IBinder> binder = serviceManager->waitForService(String16("package_native"));
56 auto packageManager = interface_cast<content::pm::IPackageManagerNative>(binder);
57 if (!packageManager) {
58 LOG(ERROR) << ": unable to access native PackageManager";
59 return nullptr;
60 }
61 return packageManager;
62}
63
64gui::Uid getPackageUid(const sp<content::pm::IPackageManagerNative>& pm,
65 const std::string& package) {
66 int32_t outUid = -1;
67 if (auto status = pm->getPackageUid(package, /*flags=*/0, AID_SYSTEM, &outUid);
68 !status.isOk()) {
69 LOG(INFO) << "Failed to get package UID from native package manager for package '"
70 << package << "': " << status;
71 return gui::Uid::INVALID;
72 }
73 return gui::Uid{static_cast<uid_t>(outUid)};
74}
75
Prabir Pradhandae52792023-12-15 07:36:40 +000076} // namespace
77
78// --- PerfettoBackend::InputEventDataSource ---
79
Prabir Pradhan58f19f62024-03-07 21:54:34 +000080PerfettoBackend::InputEventDataSource::InputEventDataSource() : mInstanceId(sNextInstanceId++) {}
81
82void PerfettoBackend::InputEventDataSource::OnSetup(const InputEventDataSource::SetupArgs& args) {
83 LOG(INFO) << "Setting up perfetto trace for: " << INPUT_EVENT_TRACE_DATA_SOURCE_NAME
84 << ", instanceId: " << mInstanceId;
85 const auto rawConfig = args.config->android_input_event_config_raw();
86 auto protoConfig = perfetto::protos::pbzero::AndroidInputEventConfig::Decoder{rawConfig};
87
88 mConfig = AndroidInputEventProtoConverter::parseConfig(protoConfig);
Prabir Pradhandae52792023-12-15 07:36:40 +000089}
90
Prabir Pradhan58f19f62024-03-07 21:54:34 +000091void PerfettoBackend::InputEventDataSource::OnStart(const InputEventDataSource::StartArgs&) {
92 LOG(INFO) << "Starting perfetto trace for: " << INPUT_EVENT_TRACE_DATA_SOURCE_NAME
93 << ", instanceId: " << mInstanceId;
94}
95
96void PerfettoBackend::InputEventDataSource::OnStop(const InputEventDataSource::StopArgs&) {
97 LOG(INFO) << "Stopping perfetto trace for: " << INPUT_EVENT_TRACE_DATA_SOURCE_NAME
98 << ", instanceId: " << mInstanceId;
Prabir Pradhandae52792023-12-15 07:36:40 +000099 InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) { ctx.Flush(); });
100}
101
Prabir Pradhanf4099452024-04-12 18:34:14 +0000102void PerfettoBackend::InputEventDataSource::initializeUidMap() {
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000103 if (mUidMap.has_value()) {
104 return;
105 }
106
107 mUidMap = {{}};
Prabir Pradhanf4099452024-04-12 18:34:14 +0000108 auto packageManager = PerfettoBackend::sPackageManagerProvider();
109 if (!packageManager) {
110 LOG(ERROR) << "Failed to initialize UID map: Could not get native package manager";
111 return;
112 }
113
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000114 for (const auto& rule : mConfig.rules) {
115 for (const auto& package : rule.matchAllPackages) {
Prabir Pradhanf4099452024-04-12 18:34:14 +0000116 mUidMap->emplace(package, getPackageUid(packageManager, package));
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000117 }
118 for (const auto& package : rule.matchAnyPackages) {
Prabir Pradhanf4099452024-04-12 18:34:14 +0000119 mUidMap->emplace(package, getPackageUid(packageManager, package));
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000120 }
121 }
122}
123
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000124bool PerfettoBackend::InputEventDataSource::shouldIgnoreTracedInputEvent(
125 const EventType& type) const {
126 if (!getFlags().test(TraceFlag::TRACE_DISPATCHER_INPUT_EVENTS)) {
127 // Ignore all input events.
128 return true;
129 }
130 if (!getFlags().test(TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH) &&
131 type != EventType::INBOUND) {
132 // When window dispatch tracing is disabled, ignore any events that are not inbound events.
133 return true;
134 }
135 return false;
136}
137
Prabir Pradhanb5682382024-02-23 22:52:31 +0000138TraceLevel PerfettoBackend::InputEventDataSource::resolveTraceLevel(
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000139 const TracedEventMetadata& metadata) const {
Prabir Pradhanb5682382024-02-23 22:52:31 +0000140 // Check for matches with the rules in the order that they are defined.
141 for (const auto& rule : mConfig.rules) {
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000142 if (ruleMatches(rule, metadata)) {
Prabir Pradhanb5682382024-02-23 22:52:31 +0000143 return rule.level;
144 }
145 }
Prabir Pradhanb5682382024-02-23 22:52:31 +0000146 // The event is not traced if it matched zero rules.
147 return TraceLevel::TRACE_LEVEL_NONE;
148}
149
150bool PerfettoBackend::InputEventDataSource::ruleMatches(const TraceRule& rule,
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000151 const TracedEventMetadata& metadata) const {
Prabir Pradhanb5682382024-02-23 22:52:31 +0000152 // By default, a rule will match all events. Return early if the rule does not match.
153
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000154 // Match the event if it is directed to a secure window.
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000155 if (rule.matchSecure.has_value() && *rule.matchSecure != metadata.isSecure) {
Prabir Pradhanb5682382024-02-23 22:52:31 +0000156 return false;
157 }
158
Prabir Pradhan04a66422024-03-15 22:45:27 +0000159 // Match the event if it was processed while there was an active InputMethod connection.
160 if (rule.matchImeConnectionActive.has_value() &&
161 *rule.matchImeConnectionActive != metadata.isImeConnectionActive) {
162 return false;
163 }
164
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000165 // Match the event if all of its target packages are explicitly allowed in the "match all" list.
166 if (!rule.matchAllPackages.empty() &&
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000167 !std::all_of(metadata.targets.begin(), metadata.targets.end(), [&](const auto& uid) {
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000168 return isPermanentlyAllowed(uid) ||
169 std::any_of(rule.matchAllPackages.begin(), rule.matchAllPackages.end(),
170 [&](const auto& pkg) { return uid == mUidMap->at(pkg); });
171 })) {
172 return false;
173 }
174
175 // Match the event if any of its target packages are allowed in the "match any" list.
176 if (!rule.matchAnyPackages.empty() &&
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000177 !std::any_of(metadata.targets.begin(), metadata.targets.end(), [&](const auto& uid) {
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000178 return std::any_of(rule.matchAnyPackages.begin(), rule.matchAnyPackages.end(),
179 [&](const auto& pkg) { return uid == mUidMap->at(pkg); });
180 })) {
181 return false;
182 }
183
184 // The event matches all matchers specified in the rule.
Prabir Pradhanb5682382024-02-23 22:52:31 +0000185 return true;
186}
187
Prabir Pradhandae52792023-12-15 07:36:40 +0000188// --- PerfettoBackend ---
189
Prabir Pradhan9a9897d2024-03-21 21:52:57 +0000190bool PerfettoBackend::sUseInProcessBackendForTest{false};
191
Prabir Pradhanf4099452024-04-12 18:34:14 +0000192std::function<sp<content::pm::IPackageManagerNative>()> PerfettoBackend::sPackageManagerProvider{
193 &getPackageManager};
194
Prabir Pradhandae52792023-12-15 07:36:40 +0000195std::once_flag PerfettoBackend::sDataSourceRegistrationFlag{};
196
Prabir Pradhan58f19f62024-03-07 21:54:34 +0000197std::atomic<int32_t> PerfettoBackend::sNextInstanceId{1};
198
Prabir Pradhanf4099452024-04-12 18:34:14 +0000199PerfettoBackend::PerfettoBackend() {
Prabir Pradhandae52792023-12-15 07:36:40 +0000200 // Use a once-flag to ensure that the data source is only registered once per boot, since
201 // we never unregister the InputEventDataSource.
202 std::call_once(sDataSourceRegistrationFlag, []() {
203 perfetto::TracingInitArgs args;
Prabir Pradhan9a9897d2024-03-21 21:52:57 +0000204 args.backends = sUseInProcessBackendForTest ? perfetto::kInProcessBackend
205 : perfetto::kSystemBackend;
Prabir Pradhandae52792023-12-15 07:36:40 +0000206 perfetto::Tracing::Initialize(args);
207
208 // Register our custom data source for input event tracing.
209 perfetto::DataSourceDescriptor dsd;
210 dsd.set_name(INPUT_EVENT_TRACE_DATA_SOURCE_NAME);
211 InputEventDataSource::Register(dsd);
212 LOG(INFO) << "InputTracer initialized for data source: "
213 << INPUT_EVENT_TRACE_DATA_SOURCE_NAME;
214 });
215}
216
Prabir Pradhan8c3b1432024-02-09 23:34:16 +0000217void PerfettoBackend::traceMotionEvent(const TracedMotionEvent& event,
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000218 const TracedEventMetadata& metadata) {
Prabir Pradhandae52792023-12-15 07:36:40 +0000219 InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000220 auto dataSource = ctx.GetDataSourceLocked();
Prabir Pradhan9a9897d2024-03-21 21:52:57 +0000221 if (!dataSource.valid()) {
222 return;
223 }
Prabir Pradhanf4099452024-04-12 18:34:14 +0000224 dataSource->initializeUidMap();
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000225 if (dataSource->shouldIgnoreTracedInputEvent(event.eventType)) {
226 return;
227 }
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000228 const TraceLevel traceLevel = dataSource->resolveTraceLevel(metadata);
Prabir Pradhanb5682382024-02-23 22:52:31 +0000229 if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) {
230 return;
231 }
232 const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED;
Prabir Pradhandae52792023-12-15 07:36:40 +0000233 auto tracePacket = ctx.NewTracePacket();
Prabir Pradhan4fc32e02024-06-14 16:00:58 +0000234 tracePacket->set_timestamp(metadata.processingTimestamp);
235 tracePacket->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
Prabir Pradhan6ef947a2024-06-10 20:00:51 +0000236 auto* winscopeExtensions = static_cast<perfetto::protos::pbzero::WinscopeExtensionsImpl*>(
237 tracePacket->set_winscope_extensions());
238 auto* inputEvent = winscopeExtensions->set_android_input_event();
Prabir Pradhanb5682382024-02-23 22:52:31 +0000239 auto* dispatchMotion = isRedacted ? inputEvent->set_dispatcher_motion_event_redacted()
240 : inputEvent->set_dispatcher_motion_event();
241 AndroidInputEventProtoConverter::toProtoMotionEvent(event, *dispatchMotion, isRedacted);
Prabir Pradhandae52792023-12-15 07:36:40 +0000242 });
243}
244
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000245void PerfettoBackend::traceKeyEvent(const TracedKeyEvent& event,
246 const TracedEventMetadata& metadata) {
Prabir Pradhandae52792023-12-15 07:36:40 +0000247 InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000248 auto dataSource = ctx.GetDataSourceLocked();
Prabir Pradhan9a9897d2024-03-21 21:52:57 +0000249 if (!dataSource.valid()) {
250 return;
251 }
Prabir Pradhanf4099452024-04-12 18:34:14 +0000252 dataSource->initializeUidMap();
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000253 if (dataSource->shouldIgnoreTracedInputEvent(event.eventType)) {
254 return;
255 }
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000256 const TraceLevel traceLevel = dataSource->resolveTraceLevel(metadata);
Prabir Pradhanb5682382024-02-23 22:52:31 +0000257 if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) {
258 return;
259 }
260 const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED;
Prabir Pradhandae52792023-12-15 07:36:40 +0000261 auto tracePacket = ctx.NewTracePacket();
Prabir Pradhan4fc32e02024-06-14 16:00:58 +0000262 tracePacket->set_timestamp(metadata.processingTimestamp);
263 tracePacket->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
Prabir Pradhan6ef947a2024-06-10 20:00:51 +0000264 auto* winscopeExtensions = static_cast<perfetto::protos::pbzero::WinscopeExtensionsImpl*>(
265 tracePacket->set_winscope_extensions());
266 auto* inputEvent = winscopeExtensions->set_android_input_event();
Prabir Pradhanb5682382024-02-23 22:52:31 +0000267 auto* dispatchKey = isRedacted ? inputEvent->set_dispatcher_key_event_redacted()
268 : inputEvent->set_dispatcher_key_event();
269 AndroidInputEventProtoConverter::toProtoKeyEvent(event, *dispatchKey, isRedacted);
Prabir Pradhandae52792023-12-15 07:36:40 +0000270 });
271}
272
Prabir Pradhan8c3b1432024-02-09 23:34:16 +0000273void PerfettoBackend::traceWindowDispatch(const WindowDispatchArgs& dispatchArgs,
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000274 const TracedEventMetadata& metadata) {
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000275 InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000276 auto dataSource = ctx.GetDataSourceLocked();
Prabir Pradhan9a9897d2024-03-21 21:52:57 +0000277 if (!dataSource.valid()) {
278 return;
279 }
Prabir Pradhanf4099452024-04-12 18:34:14 +0000280 dataSource->initializeUidMap();
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000281 if (!dataSource->getFlags().test(TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH)) {
282 return;
283 }
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000284 const TraceLevel traceLevel = dataSource->resolveTraceLevel(metadata);
Prabir Pradhanb5682382024-02-23 22:52:31 +0000285 if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) {
286 return;
287 }
288 const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED;
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000289 auto tracePacket = ctx.NewTracePacket();
Prabir Pradhan4fc32e02024-06-14 16:00:58 +0000290 tracePacket->set_timestamp(dispatchArgs.deliveryTime);
291 tracePacket->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
Prabir Pradhan6ef947a2024-06-10 20:00:51 +0000292 auto* winscopeExtensions = static_cast<perfetto::protos::pbzero::WinscopeExtensionsImpl*>(
293 tracePacket->set_winscope_extensions());
294 auto* inputEvent = winscopeExtensions->set_android_input_event();
Prabir Pradhanb5682382024-02-23 22:52:31 +0000295 auto* dispatchEvent = isRedacted
296 ? inputEvent->set_dispatcher_window_dispatch_event_redacted()
297 : inputEvent->set_dispatcher_window_dispatch_event();
298 AndroidInputEventProtoConverter::toProtoWindowDispatchEvent(dispatchArgs, *dispatchEvent,
299 isRedacted);
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000300 });
Prabir Pradhandae52792023-12-15 07:36:40 +0000301}
302
303} // namespace android::inputdispatcher::trace::impl