blob: 9b9633a1bd25e294aa99c8753f8c36c6a26d8232 [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 Pradhanbf3c8322024-02-23 02:38:36 +000026#include <private/android_filesystem_config.h>
Prabir Pradhanf4099452024-04-12 18:34:14 +000027#include <utils/String16.h>
Prabir Pradhandae52792023-12-15 07:36:40 +000028
29namespace android::inputdispatcher::trace::impl {
30
31namespace {
32
33constexpr auto INPUT_EVENT_TRACE_DATA_SOURCE_NAME = "android.input.inputevent";
34
Prabir Pradhanbf3c8322024-02-23 02:38:36 +000035bool isPermanentlyAllowed(gui::Uid uid) {
36 switch (uid.val()) {
37 case AID_SYSTEM:
38 case AID_SHELL:
39 case AID_ROOT:
40 return true;
41 default:
42 return false;
43 }
44}
45
Prabir Pradhanf4099452024-04-12 18:34:14 +000046sp<content::pm::IPackageManagerNative> getPackageManager() {
47 sp<IServiceManager> serviceManager = defaultServiceManager();
48 if (!serviceManager) {
49 LOG(ERROR) << __func__ << ": unable to access native ServiceManager";
50 return nullptr;
51 }
52
53 sp<IBinder> binder = serviceManager->waitForService(String16("package_native"));
54 auto packageManager = interface_cast<content::pm::IPackageManagerNative>(binder);
55 if (!packageManager) {
56 LOG(ERROR) << ": unable to access native PackageManager";
57 return nullptr;
58 }
59 return packageManager;
60}
61
62gui::Uid getPackageUid(const sp<content::pm::IPackageManagerNative>& pm,
63 const std::string& package) {
64 int32_t outUid = -1;
65 if (auto status = pm->getPackageUid(package, /*flags=*/0, AID_SYSTEM, &outUid);
66 !status.isOk()) {
67 LOG(INFO) << "Failed to get package UID from native package manager for package '"
68 << package << "': " << status;
69 return gui::Uid::INVALID;
70 }
71 return gui::Uid{static_cast<uid_t>(outUid)};
72}
73
Prabir Pradhandae52792023-12-15 07:36:40 +000074} // namespace
75
76// --- PerfettoBackend::InputEventDataSource ---
77
Prabir Pradhan58f19f62024-03-07 21:54:34 +000078PerfettoBackend::InputEventDataSource::InputEventDataSource() : mInstanceId(sNextInstanceId++) {}
79
80void PerfettoBackend::InputEventDataSource::OnSetup(const InputEventDataSource::SetupArgs& args) {
81 LOG(INFO) << "Setting up perfetto trace for: " << INPUT_EVENT_TRACE_DATA_SOURCE_NAME
82 << ", instanceId: " << mInstanceId;
83 const auto rawConfig = args.config->android_input_event_config_raw();
84 auto protoConfig = perfetto::protos::pbzero::AndroidInputEventConfig::Decoder{rawConfig};
85
86 mConfig = AndroidInputEventProtoConverter::parseConfig(protoConfig);
Prabir Pradhandae52792023-12-15 07:36:40 +000087}
88
Prabir Pradhan58f19f62024-03-07 21:54:34 +000089void PerfettoBackend::InputEventDataSource::OnStart(const InputEventDataSource::StartArgs&) {
90 LOG(INFO) << "Starting perfetto trace for: " << INPUT_EVENT_TRACE_DATA_SOURCE_NAME
91 << ", instanceId: " << mInstanceId;
92}
93
94void PerfettoBackend::InputEventDataSource::OnStop(const InputEventDataSource::StopArgs&) {
95 LOG(INFO) << "Stopping perfetto trace for: " << INPUT_EVENT_TRACE_DATA_SOURCE_NAME
96 << ", instanceId: " << mInstanceId;
Prabir Pradhandae52792023-12-15 07:36:40 +000097 InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) { ctx.Flush(); });
98}
99
Prabir Pradhanf4099452024-04-12 18:34:14 +0000100void PerfettoBackend::InputEventDataSource::initializeUidMap() {
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000101 if (mUidMap.has_value()) {
102 return;
103 }
104
105 mUidMap = {{}};
Prabir Pradhanf4099452024-04-12 18:34:14 +0000106 auto packageManager = PerfettoBackend::sPackageManagerProvider();
107 if (!packageManager) {
108 LOG(ERROR) << "Failed to initialize UID map: Could not get native package manager";
109 return;
110 }
111
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000112 for (const auto& rule : mConfig.rules) {
113 for (const auto& package : rule.matchAllPackages) {
Prabir Pradhanf4099452024-04-12 18:34:14 +0000114 mUidMap->emplace(package, getPackageUid(packageManager, package));
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000115 }
116 for (const auto& package : rule.matchAnyPackages) {
Prabir Pradhanf4099452024-04-12 18:34:14 +0000117 mUidMap->emplace(package, getPackageUid(packageManager, package));
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000118 }
119 }
120}
121
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000122bool PerfettoBackend::InputEventDataSource::shouldIgnoreTracedInputEvent(
123 const EventType& type) const {
124 if (!getFlags().test(TraceFlag::TRACE_DISPATCHER_INPUT_EVENTS)) {
125 // Ignore all input events.
126 return true;
127 }
128 if (!getFlags().test(TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH) &&
129 type != EventType::INBOUND) {
130 // When window dispatch tracing is disabled, ignore any events that are not inbound events.
131 return true;
132 }
133 return false;
134}
135
Prabir Pradhanb5682382024-02-23 22:52:31 +0000136TraceLevel PerfettoBackend::InputEventDataSource::resolveTraceLevel(
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000137 const TracedEventMetadata& metadata) const {
Prabir Pradhanb5682382024-02-23 22:52:31 +0000138 // Check for matches with the rules in the order that they are defined.
139 for (const auto& rule : mConfig.rules) {
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000140 if (ruleMatches(rule, metadata)) {
Prabir Pradhanb5682382024-02-23 22:52:31 +0000141 return rule.level;
142 }
143 }
Prabir Pradhanb5682382024-02-23 22:52:31 +0000144 // The event is not traced if it matched zero rules.
145 return TraceLevel::TRACE_LEVEL_NONE;
146}
147
148bool PerfettoBackend::InputEventDataSource::ruleMatches(const TraceRule& rule,
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000149 const TracedEventMetadata& metadata) const {
Prabir Pradhanb5682382024-02-23 22:52:31 +0000150 // By default, a rule will match all events. Return early if the rule does not match.
151
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000152 // Match the event if it is directed to a secure window.
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000153 if (rule.matchSecure.has_value() && *rule.matchSecure != metadata.isSecure) {
Prabir Pradhanb5682382024-02-23 22:52:31 +0000154 return false;
155 }
156
Prabir Pradhan04a66422024-03-15 22:45:27 +0000157 // Match the event if it was processed while there was an active InputMethod connection.
158 if (rule.matchImeConnectionActive.has_value() &&
159 *rule.matchImeConnectionActive != metadata.isImeConnectionActive) {
160 return false;
161 }
162
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000163 // Match the event if all of its target packages are explicitly allowed in the "match all" list.
164 if (!rule.matchAllPackages.empty() &&
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000165 !std::all_of(metadata.targets.begin(), metadata.targets.end(), [&](const auto& uid) {
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000166 return isPermanentlyAllowed(uid) ||
167 std::any_of(rule.matchAllPackages.begin(), rule.matchAllPackages.end(),
168 [&](const auto& pkg) { return uid == mUidMap->at(pkg); });
169 })) {
170 return false;
171 }
172
173 // Match the event if any of its target packages are allowed in the "match any" list.
174 if (!rule.matchAnyPackages.empty() &&
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000175 !std::any_of(metadata.targets.begin(), metadata.targets.end(), [&](const auto& uid) {
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000176 return std::any_of(rule.matchAnyPackages.begin(), rule.matchAnyPackages.end(),
177 [&](const auto& pkg) { return uid == mUidMap->at(pkg); });
178 })) {
179 return false;
180 }
181
182 // The event matches all matchers specified in the rule.
Prabir Pradhanb5682382024-02-23 22:52:31 +0000183 return true;
184}
185
Prabir Pradhandae52792023-12-15 07:36:40 +0000186// --- PerfettoBackend ---
187
Prabir Pradhan9a9897d2024-03-21 21:52:57 +0000188bool PerfettoBackend::sUseInProcessBackendForTest{false};
189
Prabir Pradhanf4099452024-04-12 18:34:14 +0000190std::function<sp<content::pm::IPackageManagerNative>()> PerfettoBackend::sPackageManagerProvider{
191 &getPackageManager};
192
Prabir Pradhandae52792023-12-15 07:36:40 +0000193std::once_flag PerfettoBackend::sDataSourceRegistrationFlag{};
194
Prabir Pradhan58f19f62024-03-07 21:54:34 +0000195std::atomic<int32_t> PerfettoBackend::sNextInstanceId{1};
196
Prabir Pradhanf4099452024-04-12 18:34:14 +0000197PerfettoBackend::PerfettoBackend() {
Prabir Pradhandae52792023-12-15 07:36:40 +0000198 // Use a once-flag to ensure that the data source is only registered once per boot, since
199 // we never unregister the InputEventDataSource.
200 std::call_once(sDataSourceRegistrationFlag, []() {
201 perfetto::TracingInitArgs args;
Prabir Pradhan9a9897d2024-03-21 21:52:57 +0000202 args.backends = sUseInProcessBackendForTest ? perfetto::kInProcessBackend
203 : perfetto::kSystemBackend;
Prabir Pradhandae52792023-12-15 07:36:40 +0000204 perfetto::Tracing::Initialize(args);
205
206 // Register our custom data source for input event tracing.
207 perfetto::DataSourceDescriptor dsd;
208 dsd.set_name(INPUT_EVENT_TRACE_DATA_SOURCE_NAME);
209 InputEventDataSource::Register(dsd);
210 LOG(INFO) << "InputTracer initialized for data source: "
211 << INPUT_EVENT_TRACE_DATA_SOURCE_NAME;
212 });
213}
214
Prabir Pradhan8c3b1432024-02-09 23:34:16 +0000215void PerfettoBackend::traceMotionEvent(const TracedMotionEvent& event,
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000216 const TracedEventMetadata& metadata) {
Prabir Pradhandae52792023-12-15 07:36:40 +0000217 InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000218 auto dataSource = ctx.GetDataSourceLocked();
Prabir Pradhan9a9897d2024-03-21 21:52:57 +0000219 if (!dataSource.valid()) {
220 return;
221 }
Prabir Pradhanf4099452024-04-12 18:34:14 +0000222 dataSource->initializeUidMap();
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000223 if (dataSource->shouldIgnoreTracedInputEvent(event.eventType)) {
224 return;
225 }
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000226 const TraceLevel traceLevel = dataSource->resolveTraceLevel(metadata);
Prabir Pradhanb5682382024-02-23 22:52:31 +0000227 if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) {
228 return;
229 }
230 const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED;
Prabir Pradhandae52792023-12-15 07:36:40 +0000231 auto tracePacket = ctx.NewTracePacket();
Priyanka Advani8779d082024-06-10 19:07:02 +0000232 auto* inputEvent = tracePacket->set_android_input_event();
Prabir Pradhanb5682382024-02-23 22:52:31 +0000233 auto* dispatchMotion = isRedacted ? inputEvent->set_dispatcher_motion_event_redacted()
234 : inputEvent->set_dispatcher_motion_event();
235 AndroidInputEventProtoConverter::toProtoMotionEvent(event, *dispatchMotion, isRedacted);
Prabir Pradhandae52792023-12-15 07:36:40 +0000236 });
237}
238
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000239void PerfettoBackend::traceKeyEvent(const TracedKeyEvent& event,
240 const TracedEventMetadata& metadata) {
Prabir Pradhandae52792023-12-15 07:36:40 +0000241 InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000242 auto dataSource = ctx.GetDataSourceLocked();
Prabir Pradhan9a9897d2024-03-21 21:52:57 +0000243 if (!dataSource.valid()) {
244 return;
245 }
Prabir Pradhanf4099452024-04-12 18:34:14 +0000246 dataSource->initializeUidMap();
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000247 if (dataSource->shouldIgnoreTracedInputEvent(event.eventType)) {
248 return;
249 }
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000250 const TraceLevel traceLevel = dataSource->resolveTraceLevel(metadata);
Prabir Pradhanb5682382024-02-23 22:52:31 +0000251 if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) {
252 return;
253 }
254 const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED;
Prabir Pradhandae52792023-12-15 07:36:40 +0000255 auto tracePacket = ctx.NewTracePacket();
Priyanka Advani8779d082024-06-10 19:07:02 +0000256 auto* inputEvent = tracePacket->set_android_input_event();
Prabir Pradhanb5682382024-02-23 22:52:31 +0000257 auto* dispatchKey = isRedacted ? inputEvent->set_dispatcher_key_event_redacted()
258 : inputEvent->set_dispatcher_key_event();
259 AndroidInputEventProtoConverter::toProtoKeyEvent(event, *dispatchKey, isRedacted);
Prabir Pradhandae52792023-12-15 07:36:40 +0000260 });
261}
262
Prabir Pradhan8c3b1432024-02-09 23:34:16 +0000263void PerfettoBackend::traceWindowDispatch(const WindowDispatchArgs& dispatchArgs,
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000264 const TracedEventMetadata& metadata) {
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000265 InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000266 auto dataSource = ctx.GetDataSourceLocked();
Prabir Pradhan9a9897d2024-03-21 21:52:57 +0000267 if (!dataSource.valid()) {
268 return;
269 }
Prabir Pradhanf4099452024-04-12 18:34:14 +0000270 dataSource->initializeUidMap();
Prabir Pradhan4c49aad2024-02-08 20:42:35 +0000271 if (!dataSource->getFlags().test(TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH)) {
272 return;
273 }
Prabir Pradhanc7edaaa2024-03-15 15:31:02 +0000274 const TraceLevel traceLevel = dataSource->resolveTraceLevel(metadata);
Prabir Pradhanb5682382024-02-23 22:52:31 +0000275 if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) {
276 return;
277 }
278 const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED;
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000279 auto tracePacket = ctx.NewTracePacket();
Priyanka Advani8779d082024-06-10 19:07:02 +0000280 auto* inputEvent = tracePacket->set_android_input_event();
Prabir Pradhanb5682382024-02-23 22:52:31 +0000281 auto* dispatchEvent = isRedacted
282 ? inputEvent->set_dispatcher_window_dispatch_event_redacted()
283 : inputEvent->set_dispatcher_window_dispatch_event();
284 AndroidInputEventProtoConverter::toProtoWindowDispatchEvent(dispatchArgs, *dispatchEvent,
285 isRedacted);
Prabir Pradhanadc59b42023-12-15 05:34:11 +0000286 });
Prabir Pradhandae52792023-12-15 07:36:40 +0000287}
288
289} // namespace android::inputdispatcher::trace::impl