Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 1 | /* |
| 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 Pradhan | f409945 | 2024-04-12 18:34:14 +0000 | [diff] [blame^] | 24 | #include <binder/IServiceManager.h> |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 25 | #include <perfetto/trace/android/android_input_event.pbzero.h> |
Prabir Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 26 | #include <private/android_filesystem_config.h> |
Prabir Pradhan | f409945 | 2024-04-12 18:34:14 +0000 | [diff] [blame^] | 27 | #include <utils/String16.h> |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 28 | |
| 29 | namespace android::inputdispatcher::trace::impl { |
| 30 | |
| 31 | namespace { |
| 32 | |
| 33 | constexpr auto INPUT_EVENT_TRACE_DATA_SOURCE_NAME = "android.input.inputevent"; |
| 34 | |
Prabir Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 35 | bool 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 Pradhan | f409945 | 2024-04-12 18:34:14 +0000 | [diff] [blame^] | 46 | sp<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 | |
| 62 | gui::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 Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 74 | } // namespace |
| 75 | |
| 76 | // --- PerfettoBackend::InputEventDataSource --- |
| 77 | |
Prabir Pradhan | 58f19f6 | 2024-03-07 21:54:34 +0000 | [diff] [blame] | 78 | PerfettoBackend::InputEventDataSource::InputEventDataSource() : mInstanceId(sNextInstanceId++) {} |
| 79 | |
| 80 | void 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 Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 87 | } |
| 88 | |
Prabir Pradhan | 58f19f6 | 2024-03-07 21:54:34 +0000 | [diff] [blame] | 89 | void PerfettoBackend::InputEventDataSource::OnStart(const InputEventDataSource::StartArgs&) { |
| 90 | LOG(INFO) << "Starting perfetto trace for: " << INPUT_EVENT_TRACE_DATA_SOURCE_NAME |
| 91 | << ", instanceId: " << mInstanceId; |
| 92 | } |
| 93 | |
| 94 | void PerfettoBackend::InputEventDataSource::OnStop(const InputEventDataSource::StopArgs&) { |
| 95 | LOG(INFO) << "Stopping perfetto trace for: " << INPUT_EVENT_TRACE_DATA_SOURCE_NAME |
| 96 | << ", instanceId: " << mInstanceId; |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 97 | InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) { ctx.Flush(); }); |
| 98 | } |
| 99 | |
Prabir Pradhan | f409945 | 2024-04-12 18:34:14 +0000 | [diff] [blame^] | 100 | void PerfettoBackend::InputEventDataSource::initializeUidMap() { |
Prabir Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 101 | if (mUidMap.has_value()) { |
| 102 | return; |
| 103 | } |
| 104 | |
| 105 | mUidMap = {{}}; |
Prabir Pradhan | f409945 | 2024-04-12 18:34:14 +0000 | [diff] [blame^] | 106 | 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 Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 112 | for (const auto& rule : mConfig.rules) { |
| 113 | for (const auto& package : rule.matchAllPackages) { |
Prabir Pradhan | f409945 | 2024-04-12 18:34:14 +0000 | [diff] [blame^] | 114 | mUidMap->emplace(package, getPackageUid(packageManager, package)); |
Prabir Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 115 | } |
| 116 | for (const auto& package : rule.matchAnyPackages) { |
Prabir Pradhan | f409945 | 2024-04-12 18:34:14 +0000 | [diff] [blame^] | 117 | mUidMap->emplace(package, getPackageUid(packageManager, package)); |
Prabir Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 118 | } |
| 119 | } |
| 120 | } |
| 121 | |
Prabir Pradhan | 4c49aad | 2024-02-08 20:42:35 +0000 | [diff] [blame] | 122 | bool 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 Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 136 | TraceLevel PerfettoBackend::InputEventDataSource::resolveTraceLevel( |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 137 | const TracedEventMetadata& metadata) const { |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 138 | // Check for matches with the rules in the order that they are defined. |
| 139 | for (const auto& rule : mConfig.rules) { |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 140 | if (ruleMatches(rule, metadata)) { |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 141 | return rule.level; |
| 142 | } |
| 143 | } |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 144 | // The event is not traced if it matched zero rules. |
| 145 | return TraceLevel::TRACE_LEVEL_NONE; |
| 146 | } |
| 147 | |
| 148 | bool PerfettoBackend::InputEventDataSource::ruleMatches(const TraceRule& rule, |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 149 | const TracedEventMetadata& metadata) const { |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 150 | // By default, a rule will match all events. Return early if the rule does not match. |
| 151 | |
Prabir Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 152 | // Match the event if it is directed to a secure window. |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 153 | if (rule.matchSecure.has_value() && *rule.matchSecure != metadata.isSecure) { |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 154 | return false; |
| 155 | } |
| 156 | |
Prabir Pradhan | 04a6642 | 2024-03-15 22:45:27 +0000 | [diff] [blame] | 157 | // 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 Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 163 | // Match the event if all of its target packages are explicitly allowed in the "match all" list. |
| 164 | if (!rule.matchAllPackages.empty() && |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 165 | !std::all_of(metadata.targets.begin(), metadata.targets.end(), [&](const auto& uid) { |
Prabir Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 166 | 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 Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 175 | !std::any_of(metadata.targets.begin(), metadata.targets.end(), [&](const auto& uid) { |
Prabir Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 176 | 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 Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 183 | return true; |
| 184 | } |
| 185 | |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 186 | // --- PerfettoBackend --- |
| 187 | |
Prabir Pradhan | 9a9897d | 2024-03-21 21:52:57 +0000 | [diff] [blame] | 188 | bool PerfettoBackend::sUseInProcessBackendForTest{false}; |
| 189 | |
Prabir Pradhan | f409945 | 2024-04-12 18:34:14 +0000 | [diff] [blame^] | 190 | std::function<sp<content::pm::IPackageManagerNative>()> PerfettoBackend::sPackageManagerProvider{ |
| 191 | &getPackageManager}; |
| 192 | |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 193 | std::once_flag PerfettoBackend::sDataSourceRegistrationFlag{}; |
| 194 | |
Prabir Pradhan | 58f19f6 | 2024-03-07 21:54:34 +0000 | [diff] [blame] | 195 | std::atomic<int32_t> PerfettoBackend::sNextInstanceId{1}; |
| 196 | |
Prabir Pradhan | f409945 | 2024-04-12 18:34:14 +0000 | [diff] [blame^] | 197 | PerfettoBackend::PerfettoBackend() { |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 198 | // 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 Pradhan | 9a9897d | 2024-03-21 21:52:57 +0000 | [diff] [blame] | 202 | args.backends = sUseInProcessBackendForTest ? perfetto::kInProcessBackend |
| 203 | : perfetto::kSystemBackend; |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 204 | 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 Pradhan | 8c3b143 | 2024-02-09 23:34:16 +0000 | [diff] [blame] | 215 | void PerfettoBackend::traceMotionEvent(const TracedMotionEvent& event, |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 216 | const TracedEventMetadata& metadata) { |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 217 | InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) { |
Prabir Pradhan | 4c49aad | 2024-02-08 20:42:35 +0000 | [diff] [blame] | 218 | auto dataSource = ctx.GetDataSourceLocked(); |
Prabir Pradhan | 9a9897d | 2024-03-21 21:52:57 +0000 | [diff] [blame] | 219 | if (!dataSource.valid()) { |
| 220 | return; |
| 221 | } |
Prabir Pradhan | f409945 | 2024-04-12 18:34:14 +0000 | [diff] [blame^] | 222 | dataSource->initializeUidMap(); |
Prabir Pradhan | 4c49aad | 2024-02-08 20:42:35 +0000 | [diff] [blame] | 223 | if (dataSource->shouldIgnoreTracedInputEvent(event.eventType)) { |
| 224 | return; |
| 225 | } |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 226 | const TraceLevel traceLevel = dataSource->resolveTraceLevel(metadata); |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 227 | if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) { |
| 228 | return; |
| 229 | } |
| 230 | const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED; |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 231 | auto tracePacket = ctx.NewTracePacket(); |
| 232 | auto* inputEvent = tracePacket->set_android_input_event(); |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 233 | auto* dispatchMotion = isRedacted ? inputEvent->set_dispatcher_motion_event_redacted() |
| 234 | : inputEvent->set_dispatcher_motion_event(); |
| 235 | AndroidInputEventProtoConverter::toProtoMotionEvent(event, *dispatchMotion, isRedacted); |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 236 | }); |
| 237 | } |
| 238 | |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 239 | void PerfettoBackend::traceKeyEvent(const TracedKeyEvent& event, |
| 240 | const TracedEventMetadata& metadata) { |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 241 | InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) { |
Prabir Pradhan | 4c49aad | 2024-02-08 20:42:35 +0000 | [diff] [blame] | 242 | auto dataSource = ctx.GetDataSourceLocked(); |
Prabir Pradhan | 9a9897d | 2024-03-21 21:52:57 +0000 | [diff] [blame] | 243 | if (!dataSource.valid()) { |
| 244 | return; |
| 245 | } |
Prabir Pradhan | f409945 | 2024-04-12 18:34:14 +0000 | [diff] [blame^] | 246 | dataSource->initializeUidMap(); |
Prabir Pradhan | 4c49aad | 2024-02-08 20:42:35 +0000 | [diff] [blame] | 247 | if (dataSource->shouldIgnoreTracedInputEvent(event.eventType)) { |
| 248 | return; |
| 249 | } |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 250 | const TraceLevel traceLevel = dataSource->resolveTraceLevel(metadata); |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 251 | if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) { |
| 252 | return; |
| 253 | } |
| 254 | const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED; |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 255 | auto tracePacket = ctx.NewTracePacket(); |
| 256 | auto* inputEvent = tracePacket->set_android_input_event(); |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 257 | auto* dispatchKey = isRedacted ? inputEvent->set_dispatcher_key_event_redacted() |
| 258 | : inputEvent->set_dispatcher_key_event(); |
| 259 | AndroidInputEventProtoConverter::toProtoKeyEvent(event, *dispatchKey, isRedacted); |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 260 | }); |
| 261 | } |
| 262 | |
Prabir Pradhan | 8c3b143 | 2024-02-09 23:34:16 +0000 | [diff] [blame] | 263 | void PerfettoBackend::traceWindowDispatch(const WindowDispatchArgs& dispatchArgs, |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 264 | const TracedEventMetadata& metadata) { |
Prabir Pradhan | adc59b4 | 2023-12-15 05:34:11 +0000 | [diff] [blame] | 265 | InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) { |
Prabir Pradhan | 4c49aad | 2024-02-08 20:42:35 +0000 | [diff] [blame] | 266 | auto dataSource = ctx.GetDataSourceLocked(); |
Prabir Pradhan | 9a9897d | 2024-03-21 21:52:57 +0000 | [diff] [blame] | 267 | if (!dataSource.valid()) { |
| 268 | return; |
| 269 | } |
Prabir Pradhan | f409945 | 2024-04-12 18:34:14 +0000 | [diff] [blame^] | 270 | dataSource->initializeUidMap(); |
Prabir Pradhan | 4c49aad | 2024-02-08 20:42:35 +0000 | [diff] [blame] | 271 | if (!dataSource->getFlags().test(TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH)) { |
| 272 | return; |
| 273 | } |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 274 | const TraceLevel traceLevel = dataSource->resolveTraceLevel(metadata); |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 275 | if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) { |
| 276 | return; |
| 277 | } |
| 278 | const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED; |
Prabir Pradhan | adc59b4 | 2023-12-15 05:34:11 +0000 | [diff] [blame] | 279 | auto tracePacket = ctx.NewTracePacket(); |
Prabir Pradhan | 8c3b143 | 2024-02-09 23:34:16 +0000 | [diff] [blame] | 280 | auto* inputEvent = tracePacket->set_android_input_event(); |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 281 | 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 Pradhan | adc59b4 | 2023-12-15 05:34:11 +0000 | [diff] [blame] | 286 | }); |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 287 | } |
| 288 | |
| 289 | } // namespace android::inputdispatcher::trace::impl |