diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2019-09-21 23:13:56 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2019-09-21 23:13:56 +0000 |
commit | 058ca6ae4d97597b5b5e2faf4453c38a6495e979 (patch) | |
tree | a63c42f851a89bb04ec523ba41bf1fe9dc09c809 | |
parent | 4a4ea9263d57076ef866214c9f59546b7ab491da (diff) | |
parent | 011cf7ffbdd32a574b285574eca9495905d6d324 (diff) | |
download | perfetto-android10-qpr1-release.tar.gz |
Snap for 5892339 from 011cf7ffbdd32a574b285574eca9495905d6d324 to qt-qpr1-releaseandroid-10.0.0_r29android-10.0.0_r28android-10.0.0_r27android-10.0.0_r26android-10.0.0_r25android-10.0.0_r24android-10.0.0_r23android-10.0.0_r22android-10.0.0_r21android-10.0.0_r20android-10.0.0_r19android-10.0.0_r18android-10.0.0_r16android-10.0.0_r15android10-qpr1-releaseandroid10-qpr1-d-releaseandroid10-qpr1-c-s1-releaseandroid10-qpr1-c-releaseandroid10-qpr1-b-s1-releaseandroid10-qpr1-b-release
Change-Id: Ib8f1a723c35f2f76e681452ba34c233015cd92ac
32 files changed, 785 insertions, 42 deletions
diff --git a/Android.bp b/Android.bp index 1325ee870..a11041afe 100644 --- a/Android.bp +++ b/Android.bp @@ -117,6 +117,7 @@ cc_binary { "src/tracing/core/trace_stats.cc", "src/tracing/core/trace_writer_impl.cc", "src/tracing/core/tracing_service_impl.cc", + "src/tracing/core/tracing_service_state.cc", "src/tracing/core/virtual_destructors.cc", ], shared_libs: [ @@ -235,8 +236,8 @@ cc_library_shared { ":perfetto_protos_perfetto_trace_trusted_lite_gen", ":perfetto_protos_perfetto_trace_zero_gen", ":perfetto_src_ipc_wire_protocol_gen", - "src/base/event.cc", "src/android_internal/lazy_library_loader.cc", + "src/base/event.cc", "src/base/file_utils.cc", "src/base/metatrace.cc", "src/base/paged_memory.cc", @@ -325,6 +326,7 @@ cc_library_shared { "src/tracing/core/trace_stats.cc", "src/tracing/core/trace_writer_impl.cc", "src/tracing/core/tracing_service_impl.cc", + "src/tracing/core/tracing_service_state.cc", "src/tracing/core/virtual_destructors.cc", ], shared_libs: [ @@ -494,6 +496,7 @@ cc_binary { "src/tracing/core/trace_stats.cc", "src/tracing/core/trace_writer_impl.cc", "src/tracing/core/tracing_service_impl.cc", + "src/tracing/core/tracing_service_state.cc", "src/tracing/core/virtual_destructors.cc", ], shared_libs: [ @@ -705,6 +708,7 @@ cc_test { "src/tracing/core/trace_stats.cc", "src/tracing/core/trace_writer_impl.cc", "src/tracing/core/tracing_service_impl.cc", + "src/tracing/core/tracing_service_state.cc", "src/tracing/core/virtual_destructors.cc", "test/end_to_end_integrationtest.cc", "test/fake_producer.cc", @@ -777,10 +781,12 @@ genrule { srcs: [ "protos/perfetto/common/android_log_constants.proto", "protos/perfetto/common/commit_data_request.proto", + "protos/perfetto/common/data_source_descriptor.proto", "protos/perfetto/common/descriptor.proto", "protos/perfetto/common/observable_events.proto", "protos/perfetto/common/sys_stats_counters.proto", "protos/perfetto/common/trace_stats.proto", + "protos/perfetto/common/tracing_service_state.proto", ], tools: [ "aprotoc", @@ -789,10 +795,12 @@ genrule { out: [ "external/perfetto/protos/perfetto/common/android_log_constants.pb.cc", "external/perfetto/protos/perfetto/common/commit_data_request.pb.cc", + "external/perfetto/protos/perfetto/common/data_source_descriptor.pb.cc", "external/perfetto/protos/perfetto/common/descriptor.pb.cc", "external/perfetto/protos/perfetto/common/observable_events.pb.cc", "external/perfetto/protos/perfetto/common/sys_stats_counters.pb.cc", "external/perfetto/protos/perfetto/common/trace_stats.pb.cc", + "external/perfetto/protos/perfetto/common/tracing_service_state.pb.cc", ], } @@ -802,10 +810,12 @@ genrule { srcs: [ "protos/perfetto/common/android_log_constants.proto", "protos/perfetto/common/commit_data_request.proto", + "protos/perfetto/common/data_source_descriptor.proto", "protos/perfetto/common/descriptor.proto", "protos/perfetto/common/observable_events.proto", "protos/perfetto/common/sys_stats_counters.proto", "protos/perfetto/common/trace_stats.proto", + "protos/perfetto/common/tracing_service_state.proto", ], tools: [ "aprotoc", @@ -814,10 +824,12 @@ genrule { out: [ "external/perfetto/protos/perfetto/common/android_log_constants.pb.h", "external/perfetto/protos/perfetto/common/commit_data_request.pb.h", + "external/perfetto/protos/perfetto/common/data_source_descriptor.pb.h", "external/perfetto/protos/perfetto/common/descriptor.pb.h", "external/perfetto/protos/perfetto/common/observable_events.pb.h", "external/perfetto/protos/perfetto/common/sys_stats_counters.pb.h", "external/perfetto/protos/perfetto/common/trace_stats.pb.h", + "external/perfetto/protos/perfetto/common/tracing_service_state.pb.h", ], export_include_dirs: [ "protos", @@ -830,10 +842,12 @@ genrule { srcs: [ "protos/perfetto/common/android_log_constants.proto", "protos/perfetto/common/commit_data_request.proto", + "protos/perfetto/common/data_source_descriptor.proto", "protos/perfetto/common/descriptor.proto", "protos/perfetto/common/observable_events.proto", "protos/perfetto/common/sys_stats_counters.proto", "protos/perfetto/common/trace_stats.proto", + "protos/perfetto/common/tracing_service_state.proto", ], tools: [ "aprotoc", @@ -843,10 +857,12 @@ genrule { out: [ "external/perfetto/protos/perfetto/common/android_log_constants.pbzero.cc", "external/perfetto/protos/perfetto/common/commit_data_request.pbzero.cc", + "external/perfetto/protos/perfetto/common/data_source_descriptor.pbzero.cc", "external/perfetto/protos/perfetto/common/descriptor.pbzero.cc", "external/perfetto/protos/perfetto/common/observable_events.pbzero.cc", "external/perfetto/protos/perfetto/common/sys_stats_counters.pbzero.cc", "external/perfetto/protos/perfetto/common/trace_stats.pbzero.cc", + "external/perfetto/protos/perfetto/common/tracing_service_state.pbzero.cc", ], } @@ -856,10 +872,12 @@ genrule { srcs: [ "protos/perfetto/common/android_log_constants.proto", "protos/perfetto/common/commit_data_request.proto", + "protos/perfetto/common/data_source_descriptor.proto", "protos/perfetto/common/descriptor.proto", "protos/perfetto/common/observable_events.proto", "protos/perfetto/common/sys_stats_counters.proto", "protos/perfetto/common/trace_stats.proto", + "protos/perfetto/common/tracing_service_state.proto", ], tools: [ "aprotoc", @@ -869,10 +887,12 @@ genrule { out: [ "external/perfetto/protos/perfetto/common/android_log_constants.pbzero.h", "external/perfetto/protos/perfetto/common/commit_data_request.pbzero.h", + "external/perfetto/protos/perfetto/common/data_source_descriptor.pbzero.h", "external/perfetto/protos/perfetto/common/descriptor.pbzero.h", "external/perfetto/protos/perfetto/common/observable_events.pbzero.h", "external/perfetto/protos/perfetto/common/sys_stats_counters.pbzero.h", "external/perfetto/protos/perfetto/common/trace_stats.pbzero.h", + "external/perfetto/protos/perfetto/common/tracing_service_state.pbzero.h", ], export_include_dirs: [ "protos", @@ -887,7 +907,6 @@ genrule { "protos/perfetto/config/android/packages_list_config.proto", "protos/perfetto/config/chrome/chrome_config.proto", "protos/perfetto/config/data_source_config.proto", - "protos/perfetto/config/data_source_descriptor.proto", "protos/perfetto/config/ftrace/ftrace_config.proto", "protos/perfetto/config/inode_file/inode_file_config.proto", "protos/perfetto/config/power/android_power_config.proto", @@ -906,7 +925,6 @@ genrule { "external/perfetto/protos/perfetto/config/android/packages_list_config.pb.cc", "external/perfetto/protos/perfetto/config/chrome/chrome_config.pb.cc", "external/perfetto/protos/perfetto/config/data_source_config.pb.cc", - "external/perfetto/protos/perfetto/config/data_source_descriptor.pb.cc", "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pb.cc", "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pb.cc", "external/perfetto/protos/perfetto/config/power/android_power_config.pb.cc", @@ -926,7 +944,6 @@ genrule { "protos/perfetto/config/android/packages_list_config.proto", "protos/perfetto/config/chrome/chrome_config.proto", "protos/perfetto/config/data_source_config.proto", - "protos/perfetto/config/data_source_descriptor.proto", "protos/perfetto/config/ftrace/ftrace_config.proto", "protos/perfetto/config/inode_file/inode_file_config.proto", "protos/perfetto/config/power/android_power_config.proto", @@ -945,7 +962,6 @@ genrule { "external/perfetto/protos/perfetto/config/android/packages_list_config.pb.h", "external/perfetto/protos/perfetto/config/chrome/chrome_config.pb.h", "external/perfetto/protos/perfetto/config/data_source_config.pb.h", - "external/perfetto/protos/perfetto/config/data_source_descriptor.pb.h", "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pb.h", "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pb.h", "external/perfetto/protos/perfetto/config/power/android_power_config.pb.h", @@ -968,7 +984,6 @@ genrule { "protos/perfetto/config/android/packages_list_config.proto", "protos/perfetto/config/chrome/chrome_config.proto", "protos/perfetto/config/data_source_config.proto", - "protos/perfetto/config/data_source_descriptor.proto", "protos/perfetto/config/ftrace/ftrace_config.proto", "protos/perfetto/config/inode_file/inode_file_config.proto", "protos/perfetto/config/power/android_power_config.proto", @@ -988,7 +1003,6 @@ genrule { "external/perfetto/protos/perfetto/config/android/packages_list_config.pbzero.cc", "external/perfetto/protos/perfetto/config/chrome/chrome_config.pbzero.cc", "external/perfetto/protos/perfetto/config/data_source_config.pbzero.cc", - "external/perfetto/protos/perfetto/config/data_source_descriptor.pbzero.cc", "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pbzero.cc", "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pbzero.cc", "external/perfetto/protos/perfetto/config/power/android_power_config.pbzero.cc", @@ -1008,7 +1022,6 @@ genrule { "protos/perfetto/config/android/packages_list_config.proto", "protos/perfetto/config/chrome/chrome_config.proto", "protos/perfetto/config/data_source_config.proto", - "protos/perfetto/config/data_source_descriptor.proto", "protos/perfetto/config/ftrace/ftrace_config.proto", "protos/perfetto/config/inode_file/inode_file_config.proto", "protos/perfetto/config/power/android_power_config.proto", @@ -1028,7 +1041,6 @@ genrule { "external/perfetto/protos/perfetto/config/android/packages_list_config.pbzero.h", "external/perfetto/protos/perfetto/config/chrome/chrome_config.pbzero.h", "external/perfetto/protos/perfetto/config/data_source_config.pbzero.h", - "external/perfetto/protos/perfetto/config/data_source_descriptor.pbzero.h", "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pbzero.h", "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pbzero.h", "external/perfetto/protos/perfetto/config/power/android_power_config.pbzero.h", @@ -2745,6 +2757,7 @@ cc_library_static { "src/tracing/core/trace_stats.cc", "src/tracing/core/trace_writer_impl.cc", "src/tracing/core/tracing_service_impl.cc", + "src/tracing/core/tracing_service_state.cc", "src/tracing/core/virtual_destructors.cc", "src/tracing/ipc/consumer/consumer_ipc_client_impl.cc", "src/tracing/ipc/default_socket.cc", @@ -3108,6 +3121,7 @@ cc_test { "src/tracing/core/trace_writer_impl_unittest.cc", "src/tracing/core/tracing_service_impl.cc", "src/tracing/core/tracing_service_impl_unittest.cc", + "src/tracing/core/tracing_service_state.cc", "src/tracing/core/virtual_destructors.cc", "src/tracing/ipc/posix_shared_memory_unittest.cc", "src/tracing/test/aligned_buffer_test.cc", @@ -3482,6 +3496,7 @@ cc_binary { "src/tracing/core/trace_stats.cc", "src/tracing/core/trace_writer_impl.cc", "src/tracing/core/tracing_service_impl.cc", + "src/tracing/core/tracing_service_state.cc", "src/tracing/core/virtual_destructors.cc", ], shared_libs: [ @@ -3589,4 +3604,4 @@ java_library_host { srcs: [ "protos/perfetto/config/perfetto_config.proto", ], -} +}
\ No newline at end of file diff --git a/gn/standalone/proto_library.gni b/gn/standalone/proto_library.gni index 2f46e9ddf..caa58d974 100644 --- a/gn/standalone/proto_library.gni +++ b/gn/standalone/proto_library.gni @@ -187,7 +187,9 @@ template("proto_library") { "visibility", ]) + set_sources_assignment_filter([ "*\.descriptor" ]) sources = get_target_outputs(":$action_name") + set_sources_assignment_filter([]) configs -= [ "//gn/standalone:extra_warnings" ] if (defined(invoker.extra_configs)) { diff --git a/include/perfetto/tracing/core/BUILD.gn b/include/perfetto/tracing/core/BUILD.gn index 18121335b..78bc8e3e6 100644 --- a/include/perfetto/tracing/core/BUILD.gn +++ b/include/perfetto/tracing/core/BUILD.gn @@ -35,5 +35,6 @@ source_set("core") { "trace_stats.h", "trace_writer.h", "tracing_service.h", + "tracing_service_state.h", ] } diff --git a/include/perfetto/tracing/core/consumer.h b/include/perfetto/tracing/core/consumer.h index cf92253e5..d8d3f137a 100644 --- a/include/perfetto/tracing/core/consumer.h +++ b/include/perfetto/tracing/core/consumer.h @@ -28,6 +28,7 @@ namespace perfetto { class TraceConfig; class TracePacket; class TraceStats; +class TracingServiceState; class PERFETTO_EXPORT Consumer { public: diff --git a/include/perfetto/tracing/core/data_source_descriptor.h b/include/perfetto/tracing/core/data_source_descriptor.h index af161ff14..79346cc1e 100644 --- a/include/perfetto/tracing/core/data_source_descriptor.h +++ b/include/perfetto/tracing/core/data_source_descriptor.h @@ -18,7 +18,7 @@ * AUTOGENERATED - DO NOT EDIT ******************************************************************************* * This file has been generated from the protobuf message - * perfetto/config/data_source_descriptor.proto + * perfetto/common/data_source_descriptor.proto * by * ../../tools/proto_to_cpp/proto_to_cpp.cc. * If you need to make changes here, change the .proto file and then run diff --git a/include/perfetto/tracing/core/tracing_service.h b/include/perfetto/tracing/core/tracing_service.h index fd109579a..5b12e11d7 100644 --- a/include/perfetto/tracing/core/tracing_service.h +++ b/include/perfetto/tracing/core/tracing_service.h @@ -39,6 +39,7 @@ class Consumer; class DataSourceDescriptor; class Producer; class SharedMemoryArbiter; +class TracingServiceState; class TraceConfig; class TraceWriter; @@ -202,6 +203,12 @@ class ConsumerEndpoint { // // TODO(eseckler): Extend this to support producers & data sources. virtual void ObserveEvents(uint32_t enabled_event_types) = 0; + + // Used to obtain the list of connected data sources and other info about + // the tracing service. + using QueryServiceStateCallback = + std::function<void(bool success, const TracingServiceState&)>; + virtual void QueryServiceState(QueryServiceStateCallback) = 0; }; // class ConsumerEndpoint. // The public API of the tracing Service business logic. diff --git a/include/perfetto/tracing/core/tracing_service_state.h b/include/perfetto/tracing/core/tracing_service_state.h new file mode 100644 index 000000000..f8a137374 --- /dev/null +++ b/include/perfetto/tracing/core/tracing_service_state.h @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2017 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. + */ + +/******************************************************************************* + * AUTOGENERATED - DO NOT EDIT + ******************************************************************************* + * This file has been generated from the protobuf message + * perfetto/common/tracing_service_state.proto + * by + * ../../tools/proto_to_cpp/proto_to_cpp.cc. + * If you need to make changes here, change the .proto file and then run + * ./tools/gen_tracing_cpp_headers_from_protos + */ + +#ifndef INCLUDE_PERFETTO_TRACING_CORE_TRACING_SERVICE_STATE_H_ +#define INCLUDE_PERFETTO_TRACING_CORE_TRACING_SERVICE_STATE_H_ + +#include <stdint.h> +#include <string> +#include <type_traits> +#include <vector> + +#include "perfetto/base/export.h" + +#include "perfetto/tracing/core/data_source_descriptor.h" + +// Forward declarations for protobuf types. +namespace perfetto { +namespace protos { +class TracingServiceState; +class TracingServiceState_Producer; +class TracingServiceState_DataSource; +class DataSourceDescriptor; +} // namespace protos +} // namespace perfetto + +namespace perfetto { + +class PERFETTO_EXPORT TracingServiceState { + public: + class PERFETTO_EXPORT Producer { + public: + Producer(); + ~Producer(); + Producer(Producer&&) noexcept; + Producer& operator=(Producer&&); + Producer(const Producer&); + Producer& operator=(const Producer&); + bool operator==(const Producer&) const; + bool operator!=(const Producer& other) const { return !(*this == other); } + + // Conversion methods from/to the corresponding protobuf types. + void FromProto(const perfetto::protos::TracingServiceState_Producer&); + void ToProto(perfetto::protos::TracingServiceState_Producer*) const; + + int32_t id() const { return id_; } + void set_id(int32_t value) { id_ = value; } + + const std::string& name() const { return name_; } + void set_name(const std::string& value) { name_ = value; } + + int32_t uid() const { return uid_; } + void set_uid(int32_t value) { uid_ = value; } + + private: + int32_t id_ = {}; + std::string name_ = {}; + int32_t uid_ = {}; + + // Allows to preserve unknown protobuf fields for compatibility + // with future versions of .proto files. + std::string unknown_fields_; + }; + + class PERFETTO_EXPORT DataSource { + public: + DataSource(); + ~DataSource(); + DataSource(DataSource&&) noexcept; + DataSource& operator=(DataSource&&); + DataSource(const DataSource&); + DataSource& operator=(const DataSource&); + bool operator==(const DataSource&) const; + bool operator!=(const DataSource& other) const { return !(*this == other); } + + // Conversion methods from/to the corresponding protobuf types. + void FromProto(const perfetto::protos::TracingServiceState_DataSource&); + void ToProto(perfetto::protos::TracingServiceState_DataSource*) const; + + const DataSourceDescriptor& descriptor() const { return descriptor_; } + DataSourceDescriptor* mutable_descriptor() { return &descriptor_; } + + int32_t producer_id() const { return producer_id_; } + void set_producer_id(int32_t value) { producer_id_ = value; } + + private: + DataSourceDescriptor descriptor_ = {}; + int32_t producer_id_ = {}; + + // Allows to preserve unknown protobuf fields for compatibility + // with future versions of .proto files. + std::string unknown_fields_; + }; + + TracingServiceState(); + ~TracingServiceState(); + TracingServiceState(TracingServiceState&&) noexcept; + TracingServiceState& operator=(TracingServiceState&&); + TracingServiceState(const TracingServiceState&); + TracingServiceState& operator=(const TracingServiceState&); + bool operator==(const TracingServiceState&) const; + bool operator!=(const TracingServiceState& other) const { + return !(*this == other); + } + + // Conversion methods from/to the corresponding protobuf types. + void FromProto(const perfetto::protos::TracingServiceState&); + void ToProto(perfetto::protos::TracingServiceState*) const; + + int producers_size() const { return static_cast<int>(producers_.size()); } + const std::vector<Producer>& producers() const { return producers_; } + std::vector<Producer>* mutable_producers() { return &producers_; } + void clear_producers() { producers_.clear(); } + Producer* add_producers() { + producers_.emplace_back(); + return &producers_.back(); + } + + int data_sources_size() const { + return static_cast<int>(data_sources_.size()); + } + const std::vector<DataSource>& data_sources() const { return data_sources_; } + std::vector<DataSource>* mutable_data_sources() { return &data_sources_; } + void clear_data_sources() { data_sources_.clear(); } + DataSource* add_data_sources() { + data_sources_.emplace_back(); + return &data_sources_.back(); + } + + int32_t num_sessions() const { return num_sessions_; } + void set_num_sessions(int32_t value) { num_sessions_ = value; } + + int32_t num_sessions_started() const { return num_sessions_started_; } + void set_num_sessions_started(int32_t value) { + num_sessions_started_ = value; + } + + private: + std::vector<Producer> producers_; + std::vector<DataSource> data_sources_; + int32_t num_sessions_ = {}; + int32_t num_sessions_started_ = {}; + + // Allows to preserve unknown protobuf fields for compatibility + // with future versions of .proto files. + std::string unknown_fields_; +}; + +} // namespace perfetto + +#endif // INCLUDE_PERFETTO_TRACING_CORE_TRACING_SERVICE_STATE_H_ diff --git a/protos/BUILD b/protos/BUILD index 833822b6e..4a8d55f2e 100644 --- a/protos/BUILD +++ b/protos/BUILD @@ -29,10 +29,12 @@ proto_library( srcs = [ "perfetto/common/android_log_constants.proto", "perfetto/common/commit_data_request.proto", + "perfetto/common/data_source_descriptor.proto", "perfetto/common/descriptor.proto", "perfetto/common/observable_events.proto", "perfetto/common/sys_stats_counters.proto", "perfetto/common/trace_stats.proto", + "perfetto/common/tracing_service_state.proto", ], has_services = 1, cc_api_version = 2, @@ -59,10 +61,12 @@ proto_library( srcs = [ "perfetto/common/android_log_constants.proto", "perfetto/common/commit_data_request.proto", + "perfetto/common/data_source_descriptor.proto", "perfetto/common/descriptor.proto", "perfetto/common/observable_events.proto", "perfetto/common/sys_stats_counters.proto", "perfetto/common/trace_stats.proto", + "perfetto/common/tracing_service_state.proto", ], ) @@ -84,7 +88,6 @@ proto_library( "perfetto/config/android/packages_list_config.proto", "perfetto/config/chrome/chrome_config.proto", "perfetto/config/data_source_config.proto", - "perfetto/config/data_source_descriptor.proto", "perfetto/config/ftrace/ftrace_config.proto", "perfetto/config/inode_file/inode_file_config.proto", "perfetto/config/power/android_power_config.proto", @@ -149,7 +152,6 @@ proto_library( "perfetto/config/android/packages_list_config.proto", "perfetto/config/chrome/chrome_config.proto", "perfetto/config/data_source_config.proto", - "perfetto/config/data_source_descriptor.proto", "perfetto/config/ftrace/ftrace_config.proto", "perfetto/config/inode_file/inode_file_config.proto", "perfetto/config/power/android_power_config.proto", diff --git a/protos/perfetto/common/BUILD.gn b/protos/perfetto/common/BUILD.gn index 36a9b20e8..e70b03c50 100644 --- a/protos/perfetto/common/BUILD.gn +++ b/protos/perfetto/common/BUILD.gn @@ -19,9 +19,11 @@ import("../../../gn/protozero_library.gni") common_sources = [ "android_log_constants.proto", "commit_data_request.proto", + "data_source_descriptor.proto", "descriptor.proto", "observable_events.proto", "sys_stats_counters.proto", + "tracing_service_state.proto", "trace_stats.proto", ] diff --git a/protos/perfetto/config/data_source_descriptor.proto b/protos/perfetto/common/data_source_descriptor.proto index 28e59d748..08ed0584f 100644 --- a/protos/perfetto/config/data_source_descriptor.proto +++ b/protos/perfetto/common/data_source_descriptor.proto @@ -42,7 +42,4 @@ message DataSourceDescriptor { // set if the data source writes packets that refer to previous trace // contents, and knows how to stop referring to the already-emitted data. optional bool handles_incremental_state_clear = 4; - - // TODO: this should have a structure to enable reflection of the proto - // fields emitted (see go/perfetto-logging). } diff --git a/protos/perfetto/common/tracing_service_state.proto b/protos/perfetto/common/tracing_service_state.proto new file mode 100644 index 000000000..dd8572c21 --- /dev/null +++ b/protos/perfetto/common/tracing_service_state.proto @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2019 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. + */ + +syntax = "proto2"; +option optimize_for = LITE_RUNTIME; + +package perfetto.protos; + +import "perfetto/common/data_source_descriptor.proto"; + +// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py +// to reflect changes in the corresponding C++ headers. + +// Reports the state of the tracing service. Used to gather details about the +// data sources connected. +// See ConsumerPort::QueryServiceState(). +message TracingServiceState { + // Describes a producer process. + message Producer { + optional int32 id = 1; // Unique ID of the producer (monotonic counter). + optional string name = 2; // Typically matches the process name. + optional int32 uid = 3; // Unix uid of the remote process. + } + + // Describes a data source registered by a producer. Data sources are listed + // regardless of the fact that they are being used or not. + message DataSource { + // Descriptor passed by the data source when calling RegisterDataSource(). + optional DataSourceDescriptor descriptor = 1; + + // ID of the producer, as per Producer.id. + optional int32 producer_id = 2; + } + + // Lists all the producers connected. + repeated Producer producers = 1; + + // Lists the data sources available. + repeated DataSource data_sources = 2; + + // Total number of tracing sessions. + optional int32 num_sessions = 3; + + // Number of tracing sessions in the started state. Always <= num_sessions. + optional int32 num_sessions_started = 4; +} diff --git a/protos/perfetto/config/BUILD.gn b/protos/perfetto/config/BUILD.gn index 2bbafbaa3..5aec57cec 100644 --- a/protos/perfetto/config/BUILD.gn +++ b/protos/perfetto/config/BUILD.gn @@ -35,7 +35,6 @@ proto_library("lite") { "android/packages_list_config.proto", "chrome/chrome_config.proto", "data_source_config.proto", - "data_source_descriptor.proto", "ftrace/ftrace_config.proto", "inode_file/inode_file_config.proto", "power/android_power_config.proto", @@ -61,7 +60,6 @@ protozero_library("zero") { "android/packages_list_config.proto", "chrome/chrome_config.proto", "data_source_config.proto", - "data_source_descriptor.proto", "ftrace/ftrace_config.proto", "inode_file/inode_file_config.proto", "power/android_power_config.proto", diff --git a/protos/perfetto/ipc/consumer_port.proto b/protos/perfetto/ipc/consumer_port.proto index 5c293abe3..595c53b45 100644 --- a/protos/perfetto/ipc/consumer_port.proto +++ b/protos/perfetto/ipc/consumer_port.proto @@ -18,6 +18,7 @@ syntax = "proto2"; option optimize_for = LITE_RUNTIME; import "perfetto/common/observable_events.proto"; +import "perfetto/common/tracing_service_state.proto"; import "perfetto/common/trace_stats.proto"; import "perfetto/config/trace_config.proto"; @@ -99,7 +100,13 @@ service ConsumerPort { rpc ObserveEvents(ObserveEventsRequest) returns (stream ObserveEventsResponse) {} - // TODO rpc ListDataSources(), for the UI. + // ---------------------------------------------------- + // All methods below have been introduced in Android R. + // ---------------------------------------------------- + + // Allows to obtain the list of data sources connected and their descriptors. + rpc QueryServiceState(QueryServiceStateRequest) + returns (stream QueryServiceStateResponse) {} } // Arguments for rpc EnableTracing(). @@ -213,3 +220,10 @@ message ObserveEventsRequest { message ObserveEventsResponse { optional ObservableEvents events = 1; } + +// Arguments for rpc QueryServiceState +message QueryServiceStateRequest {} + +message QueryServiceStateResponse { + optional TracingServiceState service_state = 1; +} diff --git a/protos/perfetto/ipc/producer_port.proto b/protos/perfetto/ipc/producer_port.proto index e129afd06..465022b57 100644 --- a/protos/perfetto/ipc/producer_port.proto +++ b/protos/perfetto/ipc/producer_port.proto @@ -19,7 +19,7 @@ option optimize_for = LITE_RUNTIME; import "perfetto/common/commit_data_request.proto"; import "perfetto/config/data_source_config.proto"; -import "perfetto/config/data_source_descriptor.proto"; +import "perfetto/common/data_source_descriptor.proto"; package perfetto.protos; diff --git a/src/perfetto_cmd/packet_writer.cc b/src/perfetto_cmd/packet_writer.cc index d2efa133b..457ed941b 100644 --- a/src/perfetto_cmd/packet_writer.cc +++ b/src/perfetto_cmd/packet_writer.cc @@ -229,7 +229,7 @@ void ZipPacketWriter::CheckEq(int actual_code, int expected_code) { void ZipPacketWriter::Deflate(const uint8_t* ptr, size_t size) { PERFETTO_CHECK(is_compressing_); - stream_.next_in = ptr; + stream_.next_in = const_cast<uint8_t*>(ptr); stream_.avail_in = static_cast<unsigned int>(size); CheckEq(deflate(&stream_, Z_NO_FLUSH), Z_OK); PERFETTO_CHECK(stream_.avail_in == 0); diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc index d050aa542..1d731664e 100644 --- a/src/perfetto_cmd/perfetto_cmd.cc +++ b/src/perfetto_cmd/perfetto_cmd.cc @@ -34,6 +34,7 @@ #include "perfetto/base/string_view.h" #include "perfetto/base/time.h" #include "perfetto/base/utils.h" +#include "perfetto/common/tracing_service_state.pb.h" #include "perfetto/config/trace_config.pb.h" #include "perfetto/protozero/proto_utils.h" #include "perfetto/traced/traced.h" @@ -42,6 +43,7 @@ #include "perfetto/tracing/core/data_source_descriptor.h" #include "perfetto/tracing/core/trace_config.h" #include "perfetto/tracing/core/trace_packet.h" +#include "perfetto/tracing/core/tracing_service_state.h" #include "src/perfetto_cmd/config.h" #include "src/perfetto_cmd/packet_writer.h" #include "src/perfetto_cmd/pbtxt_to_pb.h" @@ -162,13 +164,21 @@ using protozero::proto_utils::WriteVarInt; int PerfettoCmd::PrintUsage(const char* argv0) { PERFETTO_ELOG(R"( Usage: %s - --background -d : Exits immediately and continues tracing in background + --background -d : Exits immediately and continues tracing in + background --config -c : /path/to/trace/config/file or - for stdin --out -o : /path/to/out/trace/file or - for stdout --dropbox TAG : Upload trace into DropBox using tag TAG - --no-guardrails : Ignore guardrails triggered when using --dropbox (for testing). - --txt : Parse config as pbtxt. Not a stable API. Not for production use. - --reset-guardrails : Resets the state of the guardails and exits (for testing). + --no-guardrails : Ignore guardrails triggered when using --dropbox + (for testing). + --txt : Parse config as pbtxt. Not for production use. + Not a stable API. + --reset-guardrails : Resets the state of the guardails and exits + (for testing). + --query : Queries the service state and prints it as + human-readable text. + --query-raw : Like --query, but prints raw proto-encoded bytes + of tracing_service_state.proto. --help -h @@ -211,6 +221,8 @@ int PerfettoCmd::Main(int argc, char** argv) { OPT_ATTACH, OPT_IS_DETACHED, OPT_STOP, + OPT_QUERY, + OPT_QUERY_RAW, }; static const struct option long_options[] = { {"help", no_argument, nullptr, 'h'}, @@ -233,6 +245,8 @@ int PerfettoCmd::Main(int argc, char** argv) { {"is_detached", required_argument, nullptr, OPT_IS_DETACHED}, {"stop", no_argument, nullptr, OPT_STOP}, {"app", required_argument, nullptr, OPT_ATRACE_APP}, + {"query", no_argument, nullptr, OPT_QUERY}, + {"query-raw", no_argument, nullptr, OPT_QUERY_RAW}, {nullptr, 0, nullptr, 0}}; int option_index = 0; @@ -386,6 +400,17 @@ int PerfettoCmd::Main(int argc, char** argv) { continue; } + if (option == OPT_QUERY) { + query_service_ = true; + continue; + } + + if (option == OPT_QUERY_RAW) { + query_service_ = true; + query_service_output_raw_ = true; + continue; + } + return PrintUsage(argv[0]); } @@ -394,6 +419,11 @@ int PerfettoCmd::Main(int argc, char** argv) { config_options.categories.push_back(argv[i]); } + if (query_service_ && (is_detach() || is_attach() || background)) { + PERFETTO_ELOG("--query cannot be combined with any other argument"); + return 1; + } + if (is_detach() && is_attach()) { PERFETTO_ELOG("--attach and --detach are mutually exclusive"); return 1; @@ -418,9 +448,10 @@ int PerfettoCmd::Main(int argc, char** argv) { perfetto::protos::TraceConfig trace_config_proto; std::vector<std::string> triggers_to_activate; bool parsed = false; - if (is_attach()) { + const bool will_trace = !is_attach() && !query_service_; + if (!will_trace) { if ((!trace_config_raw.empty() || has_config_options)) { - PERFETTO_ELOG("Cannot specify a trace config with --attach"); + PERFETTO_ELOG("Cannot specify a trace config with this option"); return 1; } } else if (has_config_options) { @@ -450,7 +481,7 @@ int PerfettoCmd::Main(int argc, char** argv) { *trace_config_proto.mutable_statsd_metadata() = std::move(statsd_metadata); trace_config_->FromProto(trace_config_proto); trace_config_raw.clear(); - } else if (!is_attach()) { + } else if (will_trace) { PERFETTO_ELOG("The trace config is invalid, bailing out."); return 1; } @@ -484,10 +515,10 @@ int PerfettoCmd::Main(int argc, char** argv) { } bool open_out_file = true; - if (is_attach()) { + if (!will_trace) { open_out_file = false; if (!trace_out_path_.empty() || !dropbox_tag_.empty()) { - PERFETTO_ELOG("Can't pass an --out file (or --dropbox) to --attach"); + PERFETTO_ELOG("Can't pass an --out file (or --dropbox) with this option"); return 1; } } else if (!triggers_to_activate.empty()) { @@ -539,16 +570,24 @@ int PerfettoCmd::Main(int argc, char** argv) { // the options. if (!triggers_to_activate.empty()) { bool finished_with_success = false; - TriggerProducer producer(&task_runner_, - [this, &finished_with_success](bool success) { - finished_with_success = success; - task_runner_.Quit(); - }, - &triggers_to_activate); + TriggerProducer producer( + &task_runner_, + [this, &finished_with_success](bool success) { + finished_with_success = success; + task_runner_.Quit(); + }, + &triggers_to_activate); task_runner_.Run(); return finished_with_success ? 0 : 1; } + if (query_service_) { + consumer_endpoint_ = + ConsumerIPCClient::Connect(GetConsumerSocket(), this, &task_runner_); + task_runner_.Run(); + return 1; // We can legitimately get here if the service disconnects. + } + if (trace_config_->compression_type() == perfetto::TraceConfig::COMPRESSION_TYPE_DEFLATE) { if (packet_writer_) { @@ -599,6 +638,16 @@ int PerfettoCmd::Main(int argc, char** argv) { } void PerfettoCmd::OnConnect() { + if (query_service_) { + consumer_endpoint_->QueryServiceState( + [this](bool success, const TracingServiceState& svc_state) { + PrintServiceState(success, svc_state); + fflush(stdout); + exit(success ? 0 : 1); + }); + return; + } + if (is_attach()) { consumer_endpoint_->Attach(attach_key_); return; @@ -892,6 +941,43 @@ void PerfettoCmd::OnTraceStats(bool /*success*/, // TODO(eseckler): Support GetTraceStats(). } +void PerfettoCmd::PrintServiceState(bool success, + const TracingServiceState& svc_state) { + if (!success) { + PERFETTO_ELOG("Failed to query the service state"); + return; + } + + if (query_service_output_raw_) { + protos::TracingServiceState proto; + svc_state.ToProto(&proto); + std::string str = proto.SerializeAsString(); + fwrite(str.data(), 1, str.size(), stdout); + return; + } + + printf("Not meant for machine consumption. Use --query-raw for scripts.\n"); + + for (const auto& producer : svc_state.producers()) { + printf("producers: {\n"); + printf(" id: %d\n", producer.id()); + printf(" name: \"%s\" \n", producer.name().c_str()); + printf(" uid: %d \n", producer.uid()); + printf("}\n"); + } + + for (const auto& ds : svc_state.data_sources()) { + printf("data_sources: {\n"); + printf(" producer_id: %d\n", ds.producer_id()); + printf(" descriptor: {\n"); + printf(" name: \"%s\"\n", ds.descriptor().name().c_str()); + printf(" }\n"); + printf("}\n"); + } + printf("num_sessions: %d\n", svc_state.num_sessions()); + printf("num_sessions_started: %d\n", svc_state.num_sessions_started()); +} + void PerfettoCmd::OnObservableEvents( const ObservableEvents& /*observable_events*/) {} diff --git a/src/perfetto_cmd/perfetto_cmd.h b/src/perfetto_cmd/perfetto_cmd.h index c663ebe3f..7a98f091c 100644 --- a/src/perfetto_cmd/perfetto_cmd.h +++ b/src/perfetto_cmd/perfetto_cmd.h @@ -72,6 +72,7 @@ class PerfettoCmd : public Consumer { void SetupCtrlCSignalHandler(); void FinalizeTraceAndExit(); int PrintUsage(const char* argv0); + void PrintServiceState(bool success, const TracingServiceState&); void OnTimeout(); bool is_detach() const { return !detach_key_.empty(); } bool is_attach() const { return !attach_key_.empty(); } @@ -105,6 +106,8 @@ class PerfettoCmd : public Consumer { std::string attach_key_; bool stop_trace_once_attached_ = false; bool redetach_once_attached_ = false; + bool query_service_ = false; + bool query_service_output_raw_ = false; // How long we expect to trace for or 0 if the trace is indefinite. uint32_t expected_duration_ms_ = 0; diff --git a/src/tracing/BUILD.gn b/src/tracing/BUILD.gn index 301b9e5e3..cd9823dca 100644 --- a/src/tracing/BUILD.gn +++ b/src/tracing/BUILD.gn @@ -69,6 +69,7 @@ source_set("tracing") { "core/trace_writer_impl.h", "core/tracing_service_impl.cc", "core/tracing_service_impl.h", + "core/tracing_service_state.cc", "core/virtual_destructors.cc", ] } diff --git a/src/tracing/core/data_source_descriptor.cc b/src/tracing/core/data_source_descriptor.cc index 1ab58d45b..015c5902a 100644 --- a/src/tracing/core/data_source_descriptor.cc +++ b/src/tracing/core/data_source_descriptor.cc @@ -18,7 +18,7 @@ * AUTOGENERATED - DO NOT EDIT ******************************************************************************* * This file has been generated from the protobuf message - * perfetto/config/data_source_descriptor.proto + * perfetto/common/data_source_descriptor.proto * by * ../../tools/proto_to_cpp/proto_to_cpp.cc. * If you need to make changes here, change the .proto file and then run @@ -27,7 +27,7 @@ #include "perfetto/tracing/core/data_source_descriptor.h" -#include "perfetto/config/data_source_descriptor.pb.h" +#include "perfetto/common/data_source_descriptor.pb.h" namespace perfetto { diff --git a/src/tracing/core/tracing_service_impl.cc b/src/tracing/core/tracing_service_impl.cc index 5330ef16f..1f32db644 100644 --- a/src/tracing/core/tracing_service_impl.cc +++ b/src/tracing/core/tracing_service_impl.cc @@ -48,6 +48,7 @@ #include "perfetto/tracing/core/shared_memory_abi.h" #include "perfetto/tracing/core/trace_packet.h" #include "perfetto/tracing/core/trace_writer.h" +#include "perfetto/tracing/core/tracing_service_state.h" #include "src/tracing/core/packet_stream_validator.h" #include "src/tracing/core/shared_memory_arbiter_impl.h" #include "src/tracing/core/trace_buffer.h" @@ -2486,6 +2487,36 @@ TracingServiceImpl::ConsumerEndpointImpl::AddObservableEvents() { return observable_events_.get(); } +void TracingServiceImpl::ConsumerEndpointImpl::QueryServiceState( + QueryServiceStateCallback callback) { + PERFETTO_DCHECK_THREAD(thread_checker_); + TracingServiceState svc_state; + + const auto& sessions = service_->tracing_sessions_; + svc_state.set_num_sessions(static_cast<int>(sessions.size())); + + int num_started = 0; + for (const auto& kv : sessions) + num_started += kv.second.state == TracingSession::State::STARTED ? 1 : 0; + svc_state.set_num_sessions_started(static_cast<int>(num_started)); + + for (const auto& kv : service_->producers_) { + auto* producer = svc_state.add_producers(); + producer->set_id(static_cast<int>(kv.first)); + producer->set_name(kv.second->name_); + producer->set_uid(static_cast<int32_t>(producer->uid())); + } + + for (const auto& kv : service_->data_sources_) { + const auto& registered_data_source = kv.second; + auto* data_source = svc_state.add_data_sources(); + *data_source->mutable_descriptor() = registered_data_source.descriptor; + data_source->set_producer_id( + static_cast<int>(registered_data_source.producer_id)); + } + callback(/*success=*/true, svc_state); +} + //////////////////////////////////////////////////////////////////////////////// // TracingServiceImpl::ProducerEndpointImpl implementation //////////////////////////////////////////////////////////////////////////////// diff --git a/src/tracing/core/tracing_service_impl.h b/src/tracing/core/tracing_service_impl.h index a9fe8d2d1..038958ef7 100644 --- a/src/tracing/core/tracing_service_impl.h +++ b/src/tracing/core/tracing_service_impl.h @@ -116,6 +116,8 @@ class TracingServiceImpl : public TracingService { return base::nullopt; } + uid_t uid() const { return uid_; } + private: friend class TracingServiceImpl; friend class TracingServiceImplTest; @@ -182,6 +184,7 @@ class TracingServiceImpl : public TracingService { void Attach(const std::string& key) override; void GetTraceStats() override; void ObserveEvents(uint32_t enabled_event_types) override; + void QueryServiceState(QueryServiceStateCallback) override; // If |observe_data_source_instances == true|, will queue a task to notify // the consumer about the state change. diff --git a/src/tracing/core/tracing_service_impl_unittest.cc b/src/tracing/core/tracing_service_impl_unittest.cc index 23ea5e2d6..ae5483406 100644 --- a/src/tracing/core/tracing_service_impl_unittest.cc +++ b/src/tracing/core/tracing_service_impl_unittest.cc @@ -2760,4 +2760,55 @@ TEST_F(TracingServiceImplTest, ObserveEventsDataSourceInstances) { consumer->WaitForTracingDisabled(); } +TEST_F(TracingServiceImplTest, QueryServiceState) { + std::unique_ptr<MockConsumer> consumer = CreateMockConsumer(); + consumer->Connect(svc.get()); + + std::unique_ptr<MockProducer> producer1 = CreateMockProducer(); + producer1->Connect(svc.get(), "producer1"); + + std::unique_ptr<MockProducer> producer2 = CreateMockProducer(); + producer2->Connect(svc.get(), "producer2"); + + producer1->RegisterDataSource("common_ds"); + producer2->RegisterDataSource("common_ds"); + + producer1->RegisterDataSource("p1_ds"); + producer2->RegisterDataSource("p2_ds"); + + TracingServiceState svc_state = consumer->QueryServiceState(); + + EXPECT_EQ(svc_state.producers_size(), 2u); + EXPECT_EQ(svc_state.producers().at(0).id(), 1); + EXPECT_EQ(svc_state.producers().at(0).name(), "producer1"); + EXPECT_EQ(svc_state.producers().at(1).id(), 2); + EXPECT_EQ(svc_state.producers().at(1).name(), "producer2"); + + EXPECT_EQ(svc_state.data_sources_size(), 4u); + + EXPECT_EQ(svc_state.data_sources().at(0).producer_id(), 1); + EXPECT_EQ(svc_state.data_sources().at(0).descriptor().name(), "common_ds"); + + EXPECT_EQ(svc_state.data_sources().at(1).producer_id(), 2); + EXPECT_EQ(svc_state.data_sources().at(1).descriptor().name(), "common_ds"); + + EXPECT_EQ(svc_state.data_sources().at(2).producer_id(), 1); + EXPECT_EQ(svc_state.data_sources().at(2).descriptor().name(), "p1_ds"); + + EXPECT_EQ(svc_state.data_sources().at(3).producer_id(), 2); + EXPECT_EQ(svc_state.data_sources().at(3).descriptor().name(), "p2_ds"); + + // Test that descriptors are cleared when a producer disconnects. + producer1.reset(); + svc_state = consumer->QueryServiceState(); + + EXPECT_EQ(svc_state.producers_size(), 1u); + EXPECT_EQ(svc_state.data_sources_size(), 2u); + + EXPECT_EQ(svc_state.data_sources().at(0).producer_id(), 2); + EXPECT_EQ(svc_state.data_sources().at(0).descriptor().name(), "common_ds"); + EXPECT_EQ(svc_state.data_sources().at(1).producer_id(), 2); + EXPECT_EQ(svc_state.data_sources().at(1).descriptor().name(), "p2_ds"); +} + } // namespace perfetto diff --git a/src/tracing/core/tracing_service_state.cc b/src/tracing/core/tracing_service_state.cc new file mode 100644 index 000000000..38601f2d5 --- /dev/null +++ b/src/tracing/core/tracing_service_state.cc @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2017 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. + */ + +/******************************************************************************* + * AUTOGENERATED - DO NOT EDIT + ******************************************************************************* + * This file has been generated from the protobuf message + * perfetto/common/tracing_service_state.proto + * by + * ../../tools/proto_to_cpp/proto_to_cpp.cc. + * If you need to make changes here, change the .proto file and then run + * ./tools/gen_tracing_cpp_headers_from_protos + */ + +#include "perfetto/tracing/core/tracing_service_state.h" + +#include "perfetto/common/data_source_descriptor.pb.h" +#include "perfetto/common/tracing_service_state.pb.h" + +namespace perfetto { + +TracingServiceState::TracingServiceState() = default; +TracingServiceState::~TracingServiceState() = default; +TracingServiceState::TracingServiceState(const TracingServiceState&) = default; +TracingServiceState& TracingServiceState::operator=( + const TracingServiceState&) = default; +TracingServiceState::TracingServiceState(TracingServiceState&&) noexcept = + default; +TracingServiceState& TracingServiceState::operator=(TracingServiceState&&) = + default; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +bool TracingServiceState::operator==(const TracingServiceState& other) const { + return (producers_ == other.producers_) && + (data_sources_ == other.data_sources_) && + (num_sessions_ == other.num_sessions_) && + (num_sessions_started_ == other.num_sessions_started_); +} +#pragma GCC diagnostic pop + +void TracingServiceState::FromProto( + const perfetto::protos::TracingServiceState& proto) { + producers_.clear(); + for (const auto& field : proto.producers()) { + producers_.emplace_back(); + producers_.back().FromProto(field); + } + + data_sources_.clear(); + for (const auto& field : proto.data_sources()) { + data_sources_.emplace_back(); + data_sources_.back().FromProto(field); + } + + static_assert(sizeof(num_sessions_) == sizeof(proto.num_sessions()), + "size mismatch"); + num_sessions_ = static_cast<decltype(num_sessions_)>(proto.num_sessions()); + + static_assert( + sizeof(num_sessions_started_) == sizeof(proto.num_sessions_started()), + "size mismatch"); + num_sessions_started_ = static_cast<decltype(num_sessions_started_)>( + proto.num_sessions_started()); + unknown_fields_ = proto.unknown_fields(); +} + +void TracingServiceState::ToProto( + perfetto::protos::TracingServiceState* proto) const { + proto->Clear(); + + for (const auto& it : producers_) { + auto* entry = proto->add_producers(); + it.ToProto(entry); + } + + for (const auto& it : data_sources_) { + auto* entry = proto->add_data_sources(); + it.ToProto(entry); + } + + static_assert(sizeof(num_sessions_) == sizeof(proto->num_sessions()), + "size mismatch"); + proto->set_num_sessions( + static_cast<decltype(proto->num_sessions())>(num_sessions_)); + + static_assert( + sizeof(num_sessions_started_) == sizeof(proto->num_sessions_started()), + "size mismatch"); + proto->set_num_sessions_started( + static_cast<decltype(proto->num_sessions_started())>( + num_sessions_started_)); + *(proto->mutable_unknown_fields()) = unknown_fields_; +} + +TracingServiceState::Producer::Producer() = default; +TracingServiceState::Producer::~Producer() = default; +TracingServiceState::Producer::Producer(const TracingServiceState::Producer&) = + default; +TracingServiceState::Producer& TracingServiceState::Producer::operator=( + const TracingServiceState::Producer&) = default; +TracingServiceState::Producer::Producer( + TracingServiceState::Producer&&) noexcept = default; +TracingServiceState::Producer& TracingServiceState::Producer::operator=( + TracingServiceState::Producer&&) = default; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +bool TracingServiceState::Producer::operator==( + const TracingServiceState::Producer& other) const { + return (id_ == other.id_) && (name_ == other.name_) && (uid_ == other.uid_); +} +#pragma GCC diagnostic pop + +void TracingServiceState::Producer::FromProto( + const perfetto::protos::TracingServiceState_Producer& proto) { + static_assert(sizeof(id_) == sizeof(proto.id()), "size mismatch"); + id_ = static_cast<decltype(id_)>(proto.id()); + + static_assert(sizeof(name_) == sizeof(proto.name()), "size mismatch"); + name_ = static_cast<decltype(name_)>(proto.name()); + + static_assert(sizeof(uid_) == sizeof(proto.uid()), "size mismatch"); + uid_ = static_cast<decltype(uid_)>(proto.uid()); + unknown_fields_ = proto.unknown_fields(); +} + +void TracingServiceState::Producer::ToProto( + perfetto::protos::TracingServiceState_Producer* proto) const { + proto->Clear(); + + static_assert(sizeof(id_) == sizeof(proto->id()), "size mismatch"); + proto->set_id(static_cast<decltype(proto->id())>(id_)); + + static_assert(sizeof(name_) == sizeof(proto->name()), "size mismatch"); + proto->set_name(static_cast<decltype(proto->name())>(name_)); + + static_assert(sizeof(uid_) == sizeof(proto->uid()), "size mismatch"); + proto->set_uid(static_cast<decltype(proto->uid())>(uid_)); + *(proto->mutable_unknown_fields()) = unknown_fields_; +} + +TracingServiceState::DataSource::DataSource() = default; +TracingServiceState::DataSource::~DataSource() = default; +TracingServiceState::DataSource::DataSource( + const TracingServiceState::DataSource&) = default; +TracingServiceState::DataSource& TracingServiceState::DataSource::operator=( + const TracingServiceState::DataSource&) = default; +TracingServiceState::DataSource::DataSource( + TracingServiceState::DataSource&&) noexcept = default; +TracingServiceState::DataSource& TracingServiceState::DataSource::operator=( + TracingServiceState::DataSource&&) = default; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +bool TracingServiceState::DataSource::operator==( + const TracingServiceState::DataSource& other) const { + return (descriptor_ == other.descriptor_) && + (producer_id_ == other.producer_id_); +} +#pragma GCC diagnostic pop + +void TracingServiceState::DataSource::FromProto( + const perfetto::protos::TracingServiceState_DataSource& proto) { + descriptor_.FromProto(proto.descriptor()); + + static_assert(sizeof(producer_id_) == sizeof(proto.producer_id()), + "size mismatch"); + producer_id_ = static_cast<decltype(producer_id_)>(proto.producer_id()); + unknown_fields_ = proto.unknown_fields(); +} + +void TracingServiceState::DataSource::ToProto( + perfetto::protos::TracingServiceState_DataSource* proto) const { + proto->Clear(); + + descriptor_.ToProto(proto->mutable_descriptor()); + + static_assert(sizeof(producer_id_) == sizeof(proto->producer_id()), + "size mismatch"); + proto->set_producer_id( + static_cast<decltype(proto->producer_id())>(producer_id_)); + *(proto->mutable_unknown_fields()) = unknown_fields_; +} + +} // namespace perfetto diff --git a/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc b/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc index 26f491700..69465cf42 100644 --- a/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc +++ b/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc @@ -25,6 +25,7 @@ #include "perfetto/tracing/core/observable_events.h" #include "perfetto/tracing/core/trace_config.h" #include "perfetto/tracing/core/trace_stats.h" +#include "perfetto/tracing/core/tracing_service_state.h" // TODO(fmayer): Add a test to check to what happens when ConsumerIPCClientImpl // gets destroyed w.r.t. the Consumer pointer. Also think to lifetime of the @@ -328,4 +329,25 @@ void ConsumerIPCClientImpl::ObserveEvents(uint32_t enabled_event_types) { consumer_port_.ObserveEvents(req, std::move(async_response)); } +void ConsumerIPCClientImpl::QueryServiceState( + QueryServiceStateCallback callback) { + if (!connected_) { + PERFETTO_DLOG( + "Cannot QueryServiceState(), not connected to tracing service"); + return; + } + + protos::QueryServiceStateRequest req; + ipc::Deferred<protos::QueryServiceStateResponse> async_response; + async_response.Bind( + [callback](ipc::AsyncResult<protos::QueryServiceStateResponse> response) { + if (!response) + callback(false, TracingServiceState()); + TracingServiceState svc_state; + svc_state.FromProto(response->service_state()); + callback(true, svc_state); + }); + consumer_port_.QueryServiceState(req, std::move(async_response)); +} + } // namespace perfetto diff --git a/src/tracing/ipc/consumer/consumer_ipc_client_impl.h b/src/tracing/ipc/consumer/consumer_ipc_client_impl.h index e930ceea2..c3933c03e 100644 --- a/src/tracing/ipc/consumer/consumer_ipc_client_impl.h +++ b/src/tracing/ipc/consumer/consumer_ipc_client_impl.h @@ -70,6 +70,7 @@ class ConsumerIPCClientImpl : public TracingService::ConsumerEndpoint, void Attach(const std::string& key) override; void GetTraceStats() override; void ObserveEvents(uint32_t enabled_event_types) override; + void QueryServiceState(QueryServiceStateCallback) override; // ipc::ServiceProxy::EventListener implementation. // These methods are invoked by the IPC layer, which knows nothing about diff --git a/src/tracing/ipc/service/consumer_ipc_service.cc b/src/tracing/ipc/service/consumer_ipc_service.cc index 4e5afc972..8a31f1f15 100644 --- a/src/tracing/ipc/service/consumer_ipc_service.cc +++ b/src/tracing/ipc/service/consumer_ipc_service.cc @@ -29,6 +29,7 @@ #include "perfetto/tracing/core/trace_packet.h" #include "perfetto/tracing/core/trace_stats.h" #include "perfetto/tracing/core/tracing_service.h" +#include "perfetto/tracing/core/tracing_service_state.h" namespace perfetto { @@ -187,6 +188,22 @@ void ConsumerIPCService::ObserveEvents(const protos::ObserveEventsRequest& req, remote_consumer->CloseObserveEventsResponseStream(); } +// Called by the IPC layer. +void ConsumerIPCService::QueryServiceState( + const protos::QueryServiceStateRequest&, + DeferredQueryServiceStateResponse resp) { + RemoteConsumer* remote_consumer = GetConsumerForCurrentRequest(); + auto it = pending_query_service_responses_.insert( + pending_query_service_responses_.end(), std::move(resp)); + auto weak_this = weak_ptr_factory_.GetWeakPtr(); + auto callback = [weak_this, it](bool success, + const TracingServiceState& svc_state) { + if (weak_this) + weak_this->OnQueryServiceCallback(success, svc_state, std::move(it)); + }; + remote_consumer->service_endpoint->QueryServiceState(callback); +} + // Called by the service in response to a service_endpoint->Flush() request. void ConsumerIPCService::OnFlushCallback( bool success, @@ -200,6 +217,22 @@ void ConsumerIPCService::OnFlushCallback( } } +// Called by the service in response to service_endpoint->QueryServiceState(). +void ConsumerIPCService::OnQueryServiceCallback( + bool success, + const TracingServiceState& svc_state, + PendingQuerySvcResponses::iterator pending_response_it) { + DeferredQueryServiceStateResponse response(std::move(*pending_response_it)); + pending_query_service_responses_.erase(pending_response_it); + if (success) { + auto resp = ipc::AsyncResult<protos::QueryServiceStateResponse>::Create(); + svc_state.ToProto(resp->mutable_service_state()); + response.Resolve(std::move(resp)); + } else { + response.Reject(); + } +} + //////////////////////////////////////////////////////////////////////////////// // RemoteConsumer methods //////////////////////////////////////////////////////////////////////////////// diff --git a/src/tracing/ipc/service/consumer_ipc_service.h b/src/tracing/ipc/service/consumer_ipc_service.h index 2752fb3f4..cb9aa0f46 100644 --- a/src/tracing/ipc/service/consumer_ipc_service.h +++ b/src/tracing/ipc/service/consumer_ipc_service.h @@ -31,6 +31,8 @@ namespace perfetto { +class TracingServiceState; + namespace ipc { class Host; } // namespace ipc @@ -63,6 +65,8 @@ class ConsumerIPCService : public protos::ConsumerPort { DeferredGetTraceStatsResponse) override; void ObserveEvents(const protos::ObserveEventsRequest&, DeferredObserveEventsResponse) override; + void QueryServiceState(const protos::QueryServiceStateRequest&, + DeferredQueryServiceStateResponse) override; void OnClientDisconnected() override; private: @@ -117,6 +121,7 @@ class ConsumerIPCService : public protos::ConsumerPort { // This has to be a container that doesn't invalidate iterators. using PendingFlushResponses = std::list<DeferredFlushResponse>; + using PendingQuerySvcResponses = std::list<DeferredQueryServiceStateResponse>; ConsumerIPCService(const ConsumerIPCService&) = delete; ConsumerIPCService& operator=(const ConsumerIPCService&) = delete; @@ -126,6 +131,9 @@ class ConsumerIPCService : public protos::ConsumerPort { RemoteConsumer* GetConsumerForCurrentRequest(); void OnFlushCallback(bool success, PendingFlushResponses::iterator); + void OnQueryServiceCallback(bool success, + const TracingServiceState&, + PendingQuerySvcResponses::iterator); TracingService* const core_service_; @@ -134,6 +142,7 @@ class ConsumerIPCService : public protos::ConsumerPort { std::map<ipc::ClientID, std::unique_ptr<RemoteConsumer>> consumers_; PendingFlushResponses pending_flush_responses_; + PendingQuerySvcResponses pending_query_service_responses_; base::WeakPtrFactory<ConsumerIPCService> weak_ptr_factory_; // Keep last. }; diff --git a/src/tracing/test/mock_consumer.cc b/src/tracing/test/mock_consumer.cc index 15c140020..c2f4548c2 100644 --- a/src/tracing/test/mock_consumer.cc +++ b/src/tracing/test/mock_consumer.cc @@ -161,4 +161,20 @@ ObservableEvents MockConsumer::WaitForObservableEvents() { return events; } +TracingServiceState MockConsumer::QueryServiceState() { + static int i = 0; + TracingServiceState res; + std::string checkpoint_name = "query_service_state_" + std::to_string(i++); + auto checkpoint = task_runner_->CreateCheckpoint(checkpoint_name); + auto callback = [checkpoint, &res](bool success, + const TracingServiceState& svc_state) { + EXPECT_TRUE(success); + res = svc_state; + checkpoint(); + }; + service_endpoint_->QueryServiceState(callback); + task_runner_->RunUntilCheckpoint(checkpoint_name); + return res; +} + } // namespace perfetto diff --git a/src/tracing/test/mock_consumer.h b/src/tracing/test/mock_consumer.h index a2970429b..fe43fb50d 100644 --- a/src/tracing/test/mock_consumer.h +++ b/src/tracing/test/mock_consumer.h @@ -23,6 +23,7 @@ #include "perfetto/tracing/core/consumer.h" #include "perfetto/tracing/core/trace_packet.h" #include "perfetto/tracing/core/tracing_service.h" +#include "perfetto/tracing/core/tracing_service_state.h" #include "perfetto/trace/trace_packet.pb.h" @@ -57,6 +58,7 @@ class MockConsumer : public Consumer { std::vector<protos::TracePacket> ReadBuffers(); void GetTraceStats(); void WaitForTraceStats(bool success); + TracingServiceState QueryServiceState(); void ObserveEvents(uint32_t enabled_event_types); ObservableEvents WaitForObservableEvents(); diff --git a/test/end_to_end_integrationtest.cc b/test/end_to_end_integrationtest.cc index 2cc9a21c4..15bef9d03 100644 --- a/test/end_to_end_integrationtest.cc +++ b/test/end_to_end_integrationtest.cc @@ -601,10 +601,10 @@ TEST_F(PerfettoCmdlineTest, NoSanitizers(InvalidCases)) { EXPECT_EQ(1, ExecPerfetto({"-c", "-", "--txt", "-o", "-", "--attach=foo"}, cfg)); - EXPECT_THAT(stderr_, HasSubstr("trace config with --attach")); + EXPECT_THAT(stderr_, HasSubstr("Cannot specify a trace config")); EXPECT_EQ(1, ExecPerfetto({"-t", "2s", "-o", "-", "--attach=foo"}, cfg)); - EXPECT_THAT(stderr_, HasSubstr("trace config with --attach")); + EXPECT_THAT(stderr_, HasSubstr("Cannot specify a trace config")); EXPECT_EQ(1, ExecPerfetto({"--attach"}, cfg)); EXPECT_THAT(stderr_, ContainsRegex("option.*--attach.*requires an argument")); @@ -614,6 +614,12 @@ TEST_F(PerfettoCmdlineTest, NoSanitizers(InvalidCases)) { EXPECT_EQ(1, ExecPerfetto({"-t", "2s", "--detach=foo"}, cfg)); EXPECT_THAT(stderr_, HasSubstr("--out or --dropbox is required")); + + EXPECT_EQ(1, ExecPerfetto({"-t", "2s", "--query"}, cfg)); + EXPECT_THAT(stderr_, HasSubstr("Cannot specify a trace config")); + + EXPECT_EQ(1, ExecPerfetto({"-c", "-", "--query"}, cfg)); + EXPECT_THAT(stderr_, HasSubstr("Cannot specify a trace config")); } TEST_F(PerfettoCmdlineTest, NoSanitizers(TxtConfig)) { @@ -998,4 +1004,9 @@ TEST_F(PerfettoCmdlineTest, NoSanitizers(TriggerFromConfigStopsFileOpening)) { EXPECT_FALSE(base::ReadFile(path, &trace_str)); } +TEST_F(PerfettoCmdlineTest, NoSanitizers(Query)) { + EXPECT_EQ(0, ExecPerfetto({"--query"})) << stderr_; + EXPECT_EQ(0, ExecPerfetto({"--query-raw"})) << stderr_; +} + } // namespace perfetto diff --git a/tools/gen_all b/tools/gen_all index 27dc5f720..6b8e062b2 100755 --- a/tools/gen_all +++ b/tools/gen_all @@ -29,8 +29,9 @@ def protoc_path(out_directory): def call(cmd, *args): path = os.path.join('tools', cmd) command = [path] + list(args) + print 'Running ', ' '.join(command) try: - subprocess.check_call([path] + list(args), cwd=ROOT_DIR) + subprocess.check_call(command, cwd=ROOT_DIR) except subprocess.CalledProcessError as e: assert False, 'Command: {} failed'.format(' '.join(command)) @@ -50,6 +51,7 @@ def main(): call('gen_merged_protos') call('gen_binary_descriptors', '--protoc', protoc_path(out)) call('gen_tracing_cpp_headers_from_protos', out) + call('gen_amalgamated', '--check', '--quiet') # Keep last except AssertionError as e: if not str(e): diff --git a/tools/gen_tracing_cpp_headers_from_protos b/tools/gen_tracing_cpp_headers_from_protos index 01df69440..d70bb3cc6 100755 --- a/tools/gen_tracing_cpp_headers_from_protos +++ b/tools/gen_tracing_cpp_headers_from_protos @@ -20,13 +20,14 @@ import sys PROTOS = ( 'perfetto/common/android_log_constants.proto', 'perfetto/common/commit_data_request.proto', + 'perfetto/common/data_source_descriptor.proto', 'perfetto/common/observable_events.proto', 'perfetto/common/sys_stats_counters.proto', 'perfetto/common/trace_stats.proto', + 'perfetto/common/tracing_service_state.proto', 'perfetto/config/android/android_log_config.proto', 'perfetto/config/chrome/chrome_config.proto', 'perfetto/config/data_source_config.proto', - 'perfetto/config/data_source_descriptor.proto', 'perfetto/config/ftrace/ftrace_config.proto', 'perfetto/config/inode_file/inode_file_config.proto', 'perfetto/config/power/android_power_config.proto', |