diff options
| author | 2024-03-07 21:54:34 +0000 | |
|---|---|---|
| committer | 2024-03-18 23:11:57 +0000 | |
| commit | 58f19f6802bac3be9897c0db36c0c303b64e3822 (patch) | |
| tree | db8dd60087464e6ced310bbaa7c9e38082662a55 | |
| parent | 4b408beb74c6d9f561e36d4c416d2a94a46af29d (diff) | |
InputTracer: Read trace configuration from perfetto
Bug: 210460522
Test: manual with perfetto
Change-Id: I5eba37fd2dbf76f92c91504fed403642761cdb1d
5 files changed, 174 insertions, 6 deletions
diff --git a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp index cee741cfc7..ddc4cb3851 100644 --- a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp +++ b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp @@ -21,6 +21,23 @@ namespace android::inputdispatcher::trace { +namespace { + +using namespace ftl::flag_operators; + +// The trace config to use for maximal tracing. +const impl::TraceConfig CONFIG_TRACE_ALL{ + .flags = impl::TraceFlag::TRACE_DISPATCHER_INPUT_EVENTS | + impl::TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH, + .rules = {impl::TraceRule{.level = impl::TraceLevel::TRACE_LEVEL_COMPLETE, + .matchAllPackages = {}, + .matchAnyPackages = {}, + .matchSecure{}, + .matchImeConnectionActive = {}}}, +}; + +} // namespace + void AndroidInputEventProtoConverter::toProtoMotionEvent(const TracedMotionEvent& event, proto::AndroidMotionEvent& outProto) { outProto.set_event_id(event.id); @@ -105,4 +122,65 @@ void AndroidInputEventProtoConverter::toProtoWindowDispatchEvent( } } +impl::TraceConfig AndroidInputEventProtoConverter::parseConfig( + proto::AndroidInputEventConfig::Decoder& protoConfig) { + if (protoConfig.has_mode() && + protoConfig.mode() == proto::AndroidInputEventConfig::TRACE_MODE_TRACE_ALL) { + // User has requested the preset for maximal tracing + return CONFIG_TRACE_ALL; + } + + impl::TraceConfig config; + + // Parse trace flags + if (protoConfig.has_trace_dispatcher_input_events() && + protoConfig.trace_dispatcher_input_events()) { + config.flags |= impl::TraceFlag::TRACE_DISPATCHER_INPUT_EVENTS; + } + if (protoConfig.has_trace_dispatcher_window_dispatch() && + protoConfig.trace_dispatcher_window_dispatch()) { + config.flags |= impl::TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH; + } + + // Parse trace rules + auto rulesIt = protoConfig.rules(); + while (rulesIt) { + proto::AndroidInputEventConfig::TraceRule::Decoder protoRule{rulesIt->as_bytes()}; + config.rules.emplace_back(); + auto& rule = config.rules.back(); + + rule.level = protoRule.has_trace_level() + ? static_cast<impl::TraceLevel>(protoRule.trace_level()) + : impl::TraceLevel::TRACE_LEVEL_NONE; + + if (protoRule.has_match_all_packages()) { + auto pkgIt = protoRule.match_all_packages(); + while (pkgIt) { + rule.matchAllPackages.emplace_back(pkgIt->as_std_string()); + pkgIt++; + } + } + + if (protoRule.has_match_any_packages()) { + auto pkgIt = protoRule.match_any_packages(); + while (pkgIt) { + rule.matchAnyPackages.emplace_back(pkgIt->as_std_string()); + pkgIt++; + } + } + + if (protoRule.has_match_secure()) { + rule.matchSecure = protoRule.match_secure(); + } + + if (protoRule.has_match_ime_connection_active()) { + rule.matchImeConnectionActive = protoRule.match_ime_connection_active(); + } + + rulesIt++; + } + + return config; +} + } // namespace android::inputdispatcher::trace diff --git a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h index ab5f9ca610..bab17010ff 100644 --- a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h +++ b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h @@ -16,9 +16,11 @@ #pragma once +#include <perfetto/config/android/android_input_event_config.pbzero.h> #include <perfetto/trace/android/android_input_event.pbzero.h> #include "InputTracingBackendInterface.h" +#include "InputTracingPerfettoBackendConfig.h" namespace proto = perfetto::protos::pbzero; @@ -34,6 +36,8 @@ public: static void toProtoKeyEvent(const TracedKeyEvent& event, proto::AndroidKeyEvent& outProto); static void toProtoWindowDispatchEvent(const WindowDispatchArgs&, proto::AndroidWindowInputDispatchEvent& outProto); + + static impl::TraceConfig parseConfig(proto::AndroidInputEventConfig::Decoder& protoConfig); }; } // namespace android::inputdispatcher::trace diff --git a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp index 8ef9ca504d..e8d89e095a 100644 --- a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp +++ b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp @@ -33,12 +33,25 @@ constexpr auto INPUT_EVENT_TRACE_DATA_SOURCE_NAME = "android.input.inputevent"; // --- PerfettoBackend::InputEventDataSource --- -void PerfettoBackend::InputEventDataSource::OnStart(const perfetto::DataSourceBase::StartArgs&) { - LOG(INFO) << "Starting perfetto trace for: " << INPUT_EVENT_TRACE_DATA_SOURCE_NAME; +PerfettoBackend::InputEventDataSource::InputEventDataSource() : mInstanceId(sNextInstanceId++) {} + +void PerfettoBackend::InputEventDataSource::OnSetup(const InputEventDataSource::SetupArgs& args) { + LOG(INFO) << "Setting up perfetto trace for: " << INPUT_EVENT_TRACE_DATA_SOURCE_NAME + << ", instanceId: " << mInstanceId; + const auto rawConfig = args.config->android_input_event_config_raw(); + auto protoConfig = perfetto::protos::pbzero::AndroidInputEventConfig::Decoder{rawConfig}; + + mConfig = AndroidInputEventProtoConverter::parseConfig(protoConfig); } -void PerfettoBackend::InputEventDataSource::OnStop(const perfetto::DataSourceBase::StopArgs&) { - LOG(INFO) << "Stopping perfetto trace for: " << INPUT_EVENT_TRACE_DATA_SOURCE_NAME; +void PerfettoBackend::InputEventDataSource::OnStart(const InputEventDataSource::StartArgs&) { + LOG(INFO) << "Starting perfetto trace for: " << INPUT_EVENT_TRACE_DATA_SOURCE_NAME + << ", instanceId: " << mInstanceId; +} + +void PerfettoBackend::InputEventDataSource::OnStop(const InputEventDataSource::StopArgs&) { + LOG(INFO) << "Stopping perfetto trace for: " << INPUT_EVENT_TRACE_DATA_SOURCE_NAME + << ", instanceId: " << mInstanceId; InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) { ctx.Flush(); }); } @@ -46,6 +59,8 @@ void PerfettoBackend::InputEventDataSource::OnStop(const perfetto::DataSourceBas std::once_flag PerfettoBackend::sDataSourceRegistrationFlag{}; +std::atomic<int32_t> PerfettoBackend::sNextInstanceId{1}; + PerfettoBackend::PerfettoBackend() { // Use a once-flag to ensure that the data source is only registered once per boot, since // we never unregister the InputEventDataSource. diff --git a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.h b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.h index d4553758a4..7e1e36aba0 100644 --- a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.h +++ b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.h @@ -18,6 +18,8 @@ #include "InputTracingBackendInterface.h" +#include "InputTracingPerfettoBackendConfig.h" + #include <perfetto/tracing.h> #include <mutex> @@ -52,15 +54,24 @@ public: void traceMotionEvent(const TracedMotionEvent&, const TracedEventArgs&) override; void traceWindowDispatch(const WindowDispatchArgs&, const TracedEventArgs&) override; +private: + // Implementation of the perfetto data source. + // Each instance of the InputEventDataSource represents a different tracing session. class InputEventDataSource : public perfetto::DataSource<InputEventDataSource> { public: - void OnSetup(const SetupArgs&) override {} + explicit InputEventDataSource(); + + void OnSetup(const SetupArgs&) override; void OnStart(const StartArgs&) override; void OnStop(const StopArgs&) override; + + private: + const int32_t mInstanceId; + TraceConfig mConfig; }; -private: static std::once_flag sDataSourceRegistrationFlag; + static std::atomic<int32_t> sNextInstanceId; }; } // namespace android::inputdispatcher::trace::impl diff --git a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackendConfig.h b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackendConfig.h new file mode 100644 index 0000000000..536e32b857 --- /dev/null +++ b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackendConfig.h @@ -0,0 +1,60 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <ftl/enum.h> +#include <ftl/flags.h> +#include <perfetto/config/android/android_input_event_config.pbzero.h> +#include <vector> + +namespace android::inputdispatcher::trace::impl { + +/** Flags representing the configurations that are enabled in the trace. */ +enum class TraceFlag : uint32_t { + // Trace details about input events processed by InputDispatcher. + TRACE_DISPATCHER_INPUT_EVENTS = 0x1, + // Trace details about an event being sent to a window by InputDispatcher. + TRACE_DISPATCHER_WINDOW_DISPATCH = 0x2, + + ftl_last = TRACE_DISPATCHER_WINDOW_DISPATCH, +}; + +/** Representation of AndroidInputEventConfig::TraceLevel. */ +using TraceLevel = perfetto::protos::pbzero::AndroidInputEventConfig::TraceLevel; + +/** Representation of AndroidInputEventConfig::TraceRule. */ +struct TraceRule { + TraceLevel level; + + std::vector<std::string> matchAllPackages; + std::vector<std::string> matchAnyPackages; + std::optional<bool> matchSecure; + std::optional<bool> matchImeConnectionActive; +}; + +/** + * A complete configuration for a tracing session. + * + * The trace rules are applied as documented in the perfetto config: + * /external/perfetto/protos/perfetto/config/android/android_input_event_config.proto + */ +struct TraceConfig { + ftl::Flags<TraceFlag> flags; + std::vector<TraceRule> rules; +}; + +} // namespace android::inputdispatcher::trace::impl |