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> |
| 24 | #include <perfetto/trace/android/android_input_event.pbzero.h> |
Prabir Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 25 | #include <private/android_filesystem_config.h> |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 26 | |
| 27 | namespace android::inputdispatcher::trace::impl { |
| 28 | |
| 29 | namespace { |
| 30 | |
| 31 | constexpr auto INPUT_EVENT_TRACE_DATA_SOURCE_NAME = "android.input.inputevent"; |
| 32 | |
Prabir Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 33 | bool 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 Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 44 | } // namespace |
| 45 | |
| 46 | // --- PerfettoBackend::InputEventDataSource --- |
| 47 | |
Prabir Pradhan | 58f19f6 | 2024-03-07 21:54:34 +0000 | [diff] [blame] | 48 | PerfettoBackend::InputEventDataSource::InputEventDataSource() : mInstanceId(sNextInstanceId++) {} |
| 49 | |
| 50 | void 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 Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 57 | } |
| 58 | |
Prabir Pradhan | 58f19f6 | 2024-03-07 21:54:34 +0000 | [diff] [blame] | 59 | void PerfettoBackend::InputEventDataSource::OnStart(const InputEventDataSource::StartArgs&) { |
| 60 | LOG(INFO) << "Starting perfetto trace for: " << INPUT_EVENT_TRACE_DATA_SOURCE_NAME |
| 61 | << ", instanceId: " << mInstanceId; |
| 62 | } |
| 63 | |
| 64 | void PerfettoBackend::InputEventDataSource::OnStop(const InputEventDataSource::StopArgs&) { |
| 65 | LOG(INFO) << "Stopping perfetto trace for: " << INPUT_EVENT_TRACE_DATA_SOURCE_NAME |
| 66 | << ", instanceId: " << mInstanceId; |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 67 | InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) { ctx.Flush(); }); |
| 68 | } |
| 69 | |
Prabir Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 70 | void 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 Pradhan | 4c49aad | 2024-02-08 20:42:35 +0000 | [diff] [blame] | 86 | bool 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 Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 100 | TraceLevel PerfettoBackend::InputEventDataSource::resolveTraceLevel( |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 101 | const TracedEventMetadata& metadata) const { |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 102 | // Check for matches with the rules in the order that they are defined. |
| 103 | for (const auto& rule : mConfig.rules) { |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 104 | if (ruleMatches(rule, metadata)) { |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 105 | return rule.level; |
| 106 | } |
| 107 | } |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 108 | // The event is not traced if it matched zero rules. |
| 109 | return TraceLevel::TRACE_LEVEL_NONE; |
| 110 | } |
| 111 | |
| 112 | bool PerfettoBackend::InputEventDataSource::ruleMatches(const TraceRule& rule, |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 113 | const TracedEventMetadata& metadata) const { |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 114 | // By default, a rule will match all events. Return early if the rule does not match. |
| 115 | |
Prabir Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 116 | // Match the event if it is directed to a secure window. |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 117 | if (rule.matchSecure.has_value() && *rule.matchSecure != metadata.isSecure) { |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 118 | return false; |
| 119 | } |
| 120 | |
Prabir Pradhan | 04a6642 | 2024-03-15 22:45:27 +0000 | [diff] [blame] | 121 | // 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 Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 127 | // Match the event if all of its target packages are explicitly allowed in the "match all" list. |
| 128 | if (!rule.matchAllPackages.empty() && |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 129 | !std::all_of(metadata.targets.begin(), metadata.targets.end(), [&](const auto& uid) { |
Prabir Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 130 | 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 Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 139 | !std::any_of(metadata.targets.begin(), metadata.targets.end(), [&](const auto& uid) { |
Prabir Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 140 | 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 Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 147 | return true; |
| 148 | } |
| 149 | |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 150 | // --- PerfettoBackend --- |
| 151 | |
Prabir Pradhan | 9a9897d | 2024-03-21 21:52:57 +0000 | [diff] [blame] | 152 | bool PerfettoBackend::sUseInProcessBackendForTest{false}; |
| 153 | |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 154 | std::once_flag PerfettoBackend::sDataSourceRegistrationFlag{}; |
| 155 | |
Prabir Pradhan | 58f19f6 | 2024-03-07 21:54:34 +0000 | [diff] [blame] | 156 | std::atomic<int32_t> PerfettoBackend::sNextInstanceId{1}; |
| 157 | |
Prabir Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 158 | PerfettoBackend::PerfettoBackend(GetPackageUid getPackagesForUid) |
| 159 | : mGetPackageUid(getPackagesForUid) { |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 160 | // 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 Pradhan | 9a9897d | 2024-03-21 21:52:57 +0000 | [diff] [blame] | 164 | args.backends = sUseInProcessBackendForTest ? perfetto::kInProcessBackend |
| 165 | : perfetto::kSystemBackend; |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 166 | 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 Pradhan | 8c3b143 | 2024-02-09 23:34:16 +0000 | [diff] [blame] | 177 | void PerfettoBackend::traceMotionEvent(const TracedMotionEvent& event, |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 178 | const TracedEventMetadata& metadata) { |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 179 | InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) { |
Prabir Pradhan | 4c49aad | 2024-02-08 20:42:35 +0000 | [diff] [blame] | 180 | auto dataSource = ctx.GetDataSourceLocked(); |
Prabir Pradhan | 9a9897d | 2024-03-21 21:52:57 +0000 | [diff] [blame] | 181 | if (!dataSource.valid()) { |
| 182 | return; |
| 183 | } |
Prabir Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 184 | dataSource->initializeUidMap(mGetPackageUid); |
Prabir Pradhan | 4c49aad | 2024-02-08 20:42:35 +0000 | [diff] [blame] | 185 | if (dataSource->shouldIgnoreTracedInputEvent(event.eventType)) { |
| 186 | return; |
| 187 | } |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 188 | const TraceLevel traceLevel = dataSource->resolveTraceLevel(metadata); |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 189 | if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) { |
| 190 | return; |
| 191 | } |
| 192 | const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED; |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 193 | auto tracePacket = ctx.NewTracePacket(); |
| 194 | auto* inputEvent = tracePacket->set_android_input_event(); |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 195 | auto* dispatchMotion = isRedacted ? inputEvent->set_dispatcher_motion_event_redacted() |
| 196 | : inputEvent->set_dispatcher_motion_event(); |
| 197 | AndroidInputEventProtoConverter::toProtoMotionEvent(event, *dispatchMotion, isRedacted); |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 198 | }); |
| 199 | } |
| 200 | |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 201 | void PerfettoBackend::traceKeyEvent(const TracedKeyEvent& event, |
| 202 | const TracedEventMetadata& metadata) { |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 203 | InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) { |
Prabir Pradhan | 4c49aad | 2024-02-08 20:42:35 +0000 | [diff] [blame] | 204 | auto dataSource = ctx.GetDataSourceLocked(); |
Prabir Pradhan | 9a9897d | 2024-03-21 21:52:57 +0000 | [diff] [blame] | 205 | if (!dataSource.valid()) { |
| 206 | return; |
| 207 | } |
Prabir Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 208 | dataSource->initializeUidMap(mGetPackageUid); |
Prabir Pradhan | 4c49aad | 2024-02-08 20:42:35 +0000 | [diff] [blame] | 209 | if (dataSource->shouldIgnoreTracedInputEvent(event.eventType)) { |
| 210 | return; |
| 211 | } |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 212 | const TraceLevel traceLevel = dataSource->resolveTraceLevel(metadata); |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 213 | if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) { |
| 214 | return; |
| 215 | } |
| 216 | const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED; |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 217 | auto tracePacket = ctx.NewTracePacket(); |
| 218 | auto* inputEvent = tracePacket->set_android_input_event(); |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 219 | auto* dispatchKey = isRedacted ? inputEvent->set_dispatcher_key_event_redacted() |
| 220 | : inputEvent->set_dispatcher_key_event(); |
| 221 | AndroidInputEventProtoConverter::toProtoKeyEvent(event, *dispatchKey, isRedacted); |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 222 | }); |
| 223 | } |
| 224 | |
Prabir Pradhan | 8c3b143 | 2024-02-09 23:34:16 +0000 | [diff] [blame] | 225 | void PerfettoBackend::traceWindowDispatch(const WindowDispatchArgs& dispatchArgs, |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 226 | const TracedEventMetadata& metadata) { |
Prabir Pradhan | adc59b4 | 2023-12-15 05:34:11 +0000 | [diff] [blame] | 227 | InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) { |
Prabir Pradhan | 4c49aad | 2024-02-08 20:42:35 +0000 | [diff] [blame] | 228 | auto dataSource = ctx.GetDataSourceLocked(); |
Prabir Pradhan | 9a9897d | 2024-03-21 21:52:57 +0000 | [diff] [blame] | 229 | if (!dataSource.valid()) { |
| 230 | return; |
| 231 | } |
Prabir Pradhan | bf3c832 | 2024-02-23 02:38:36 +0000 | [diff] [blame] | 232 | dataSource->initializeUidMap(mGetPackageUid); |
Prabir Pradhan | 4c49aad | 2024-02-08 20:42:35 +0000 | [diff] [blame] | 233 | if (!dataSource->getFlags().test(TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH)) { |
| 234 | return; |
| 235 | } |
Prabir Pradhan | c7edaaa | 2024-03-15 15:31:02 +0000 | [diff] [blame] | 236 | const TraceLevel traceLevel = dataSource->resolveTraceLevel(metadata); |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 237 | if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) { |
| 238 | return; |
| 239 | } |
| 240 | const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED; |
Prabir Pradhan | adc59b4 | 2023-12-15 05:34:11 +0000 | [diff] [blame] | 241 | auto tracePacket = ctx.NewTracePacket(); |
Prabir Pradhan | 8c3b143 | 2024-02-09 23:34:16 +0000 | [diff] [blame] | 242 | auto* inputEvent = tracePacket->set_android_input_event(); |
Prabir Pradhan | b568238 | 2024-02-23 22:52:31 +0000 | [diff] [blame] | 243 | 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 Pradhan | adc59b4 | 2023-12-15 05:34:11 +0000 | [diff] [blame] | 248 | }); |
Prabir Pradhan | dae5279 | 2023-12-15 07:36:40 +0000 | [diff] [blame] | 249 | } |
| 250 | |
| 251 | } // namespace android::inputdispatcher::trace::impl |