Merge "Fix run-buildtools-binary.sh to work on my computer"
diff --git a/Android.bp b/Android.bp
index 429038f..4e32744 100644
--- a/Android.bp
+++ b/Android.bp
@@ -46,6 +46,7 @@
"src/protozero/protozero_message.cc",
"src/protozero/protozero_message_handle.cc",
"src/protozero/scattered_stream_writer.cc",
+ "src/traced/perfetto_cmd/perfetto_cmd.cc",
"src/traced/probes/probes.cc",
"src/traced/service/service.cc",
"src/tracing/core/chunked_protobuf_input_stream.cc",
@@ -63,6 +64,7 @@
"libandroid",
"liblog",
"libprotobuf-cpp-lite",
+ "libutils",
],
static_libs: [
"libgtest_prod",
@@ -80,6 +82,26 @@
defaults: [
"perfetto_defaults",
],
+ cflags: [
+ "-DPERFETTO_BUILD_WITH_ANDROID",
+ ],
+}
+
+// GN target: //:perfetto
+cc_binary {
+ name: "perfetto",
+ srcs: [
+ "src/traced/perfetto_cmd/main.cc",
+ ],
+ shared_libs: [
+ "libandroid",
+ "liblog",
+ "libtraced_shared",
+ "libutils",
+ ],
+ defaults: [
+ "perfetto_defaults",
+ ],
}
cc_defaults {
@@ -876,6 +898,7 @@
"libandroid",
"liblog",
"libtraced_shared",
+ "libutils",
],
defaults: [
"perfetto_defaults",
@@ -892,6 +915,7 @@
"libandroid",
"liblog",
"libtraced_shared",
+ "libutils",
],
defaults: [
"perfetto_defaults",
diff --git a/BUILD.gn b/BUILD.gn
index 441d438..1996c66 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -17,7 +17,10 @@
group("all") {
testonly = true # allow to build also test targets
deps = [
+ ":perfetto",
":perfetto_tests",
+ ":traced",
+ ":traced_probes",
"src/ipc/protoc_plugin:ipc_plugin($host_toolchain)",
"src/protozero/protoc_plugin($host_toolchain)",
"src/tracing:consumer_cmd",
@@ -59,11 +62,19 @@
shared_library("libtraced_shared") {
deps = [
"gn:default_deps",
+ "src/traced/perfetto_cmd",
"src/traced/probes",
"src/traced/service",
]
+ if (build_with_android) {
+ cflags = [ "-DPERFETTO_BUILD_WITH_ANDROID" ]
+ libs = [ "utils" ]
+ }
}
+ # The unprivileged trace daemon that listens for Producer and Consumer
+ # connections, handles the coordination of the tracing sessions and owns the
+ # log buffers.
executable("traced") {
deps = [
":libtraced_shared",
@@ -74,6 +85,8 @@
]
}
+ # The unprivileged daemon that is allowed to access tracefs (for ftrace).
+ # Registers as a Producer on the traced daemon.
executable("traced_probes") {
deps = [
":libtraced_shared",
@@ -83,4 +96,16 @@
"src/traced/probes/main.cc",
]
}
+
+ # The command line client for Perfetto. Allows to configure / start / stop
+ # tracing, acting as a Consumer.
+ executable("perfetto") {
+ deps = [
+ ":libtraced_shared",
+ "gn:default_deps",
+ ]
+ sources = [
+ "src/traced/perfetto_cmd/main.cc",
+ ]
+ }
}
diff --git a/build_overrides/build.gni b/build_overrides/build.gni
index b7a2bab..a89a764 100644
--- a/build_overrides/build.gni
+++ b/build_overrides/build.gni
@@ -12,8 +12,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# When building perfetto in the android tree this variable becomes magically
+# When building perfetto in the Chromium tree this variable becomes magically
# true by virtue of including //build_overrides by absolute path.
# When false, instead, the build files can assume this is a Perfetto standalone
# build.
build_with_chromium = false
+
+declare_args() {
+ # The Android blueprint file generator overrides this to true.
+ build_with_android = false
+}
diff --git a/gn/BUILD.gn b/gn/BUILD.gn
index 32569d8..a1026b6 100644
--- a/gn/BUILD.gn
+++ b/gn/BUILD.gn
@@ -66,6 +66,8 @@
}
group("protobuf_full_deps") {
+ testonly = true
+
if (!build_with_chromium) {
public_deps = [
"//buildtools:protobuf_full",
diff --git a/include/perfetto/traced/traced.h b/include/perfetto/traced/traced.h
index 0a6f6e9..a3dfaac 100644
--- a/include/perfetto/traced/traced.h
+++ b/include/perfetto/traced/traced.h
@@ -35,6 +35,7 @@
int ServiceMain(int argc, char** argv);
int ProbesMain(int argc, char** argv);
+int PerfettoCmdMain(int argc, char** argv);
} // namespace perfetto
diff --git a/src/traced/perfetto_cmd/BUILD.gn b/src/traced/perfetto_cmd/BUILD.gn
new file mode 100644
index 0000000..1f11254
--- /dev/null
+++ b/src/traced/perfetto_cmd/BUILD.gn
@@ -0,0 +1,28 @@
+# Copyright (C) 2018 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.
+
+source_set("perfetto_cmd") {
+ public_deps = [
+ "../../../include/perfetto/traced",
+ ]
+ deps = [
+ "../../../gn:default_deps",
+ "../../../protos:lite",
+ "../../base",
+ "../../tracing:ipc",
+ ]
+ sources = [
+ "perfetto_cmd.cc",
+ ]
+}
diff --git a/src/traced/perfetto_cmd/main.cc b/src/traced/perfetto_cmd/main.cc
new file mode 100644
index 0000000..dc71930
--- /dev/null
+++ b/src/traced/perfetto_cmd/main.cc
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#include <stdio.h>
+#include "perfetto/traced/traced.h"
+
+int main(int argc, char** argv) {
+ return perfetto::PerfettoCmdMain(argc, argv);
+}
diff --git a/src/traced/perfetto_cmd/perfetto_cmd.cc b/src/traced/perfetto_cmd/perfetto_cmd.cc
new file mode 100644
index 0000000..66ce34b
--- /dev/null
+++ b/src/traced/perfetto_cmd/perfetto_cmd.cc
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#include <getopt.h>
+
+#include <fstream>
+#include <iostream>
+#include <iterator>
+#include <string>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/unix_task_runner.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/traced/traced.h"
+#include "perfetto/tracing/core/consumer.h"
+#include "perfetto/tracing/core/data_source_config.h"
+#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/ipc/consumer_ipc_client.h"
+
+#include "protos/tracing_service/trace_config.pb.h"
+
+#if defined(PERFETTO_BUILD_WITH_ANDROID)
+#include "perfetto/base/android_task_runner.h"
+
+#include <utils/Looper.h>
+#include <utils/StrongPointer.h>
+#endif // defined(PERFETTO_BUILD_WITH_ANDROID)
+
+// TODO(primiano): add the ability to pass the file descriptor directly to the
+// traced service instead of receiving a copy of the chunks and writing them
+// from this process.
+namespace perfetto {
+
+#if defined(PERFETTO_BUILD_WITH_ANDROID)
+using PlatformTaskRunner = base::AndroidTaskRunner;
+#else
+using PlatformTaskRunner = base::UnixTaskRunner;
+#endif
+
+class PerfettoCmd : public Consumer {
+ public:
+ int Main(int argc, char** argv);
+ int PrintUsage(const char* argv0);
+ void OnStopTraceTimer();
+
+ // perfetto::Consumer implementation.
+ void OnConnect() override;
+ void OnDisconnect() override;
+ void OnTraceData(std::vector<TracePacket>, bool has_more) override;
+
+ private:
+ PlatformTaskRunner task_runner_;
+ std::unique_ptr<perfetto::Service::ConsumerEndpoint> consumer_endpoint_;
+ std::unique_ptr<TraceConfig> trace_config_;
+ std::ofstream trace_out_stream_;
+ std::string trace_out_path_;
+ bool did_receive_full_trace_ = false;
+};
+
+int PerfettoCmd::PrintUsage(const char* argv0) {
+ fprintf(stderr, R"(Usage: %s
+ --config -c : /path/to/trace/config/file or - for stdin
+ --out -o : /path/to/out/trace/file
+ --help
+)", argv0);
+ return 1;
+}
+
+int PerfettoCmd::Main(int argc, char** argv) {
+ static const struct option long_options[] = {
+ // |option_index| relies on the order of options, don't reshuffle them.
+ {"help", required_argument, 0, 'h'},
+ {"config", required_argument, 0, 'c'},
+ {"out", required_argument, 0, 'o'},
+ {0, 0, 0, 0}};
+
+ int option_index = 0;
+ std::string trace_config_raw;
+ for (;;) {
+ int option = getopt_long(argc, argv, "c:o:", long_options, &option_index);
+
+ if (option == -1)
+ break; // EOF.
+
+ if (option == 'c') {
+ if (strcmp(optarg, "-") == 0) {
+ std::istreambuf_iterator<char> begin(std::cin), end;
+ trace_config_raw.assign(begin, end);
+ } else if (strcmp(optarg, ":test") == 0) {
+ // TODO(primiano): temporary for testing only.
+ perfetto::protos::TraceConfig test_config;
+ test_config.add_buffers()->set_size_kb(4096 * 10);
+ test_config.set_duration_ms(3000);
+ auto* ds_config = test_config.add_data_sources()->mutable_config();
+ ds_config->set_name("perfetto.test");
+ ds_config->set_target_buffer(0);
+ ds_config->set_trace_category_filters("foo,bar");
+ test_config.SerializeToString(&trace_config_raw);
+ } else {
+ std::ifstream file_stream;
+ file_stream.open(optarg, std::ios_base::in | std::ios_base::binary);
+ if (!file_stream.is_open()) {
+ PERFETTO_ELOG("Could not open %s", optarg);
+ return 1;
+ }
+ std::istreambuf_iterator<char> begin(file_stream), end;
+ trace_config_raw.assign(begin, end);
+ }
+ continue;
+ }
+
+ if (option == 'o') {
+ trace_out_path_ = optarg;
+ trace_out_stream_.open(trace_out_path_ + ".tmp",
+ std::ios_base::out | std::ios_base::binary);
+ if (!trace_out_stream_.is_open()) {
+ PERFETTO_ELOG("Could not open %s", trace_out_path_.c_str());
+ return 1;
+ }
+ continue;
+ }
+
+ return PrintUsage(argv[0]);
+ }
+
+ if (trace_config_raw.empty())
+ return PrintUsage(argv[0]);
+ perfetto::protos::TraceConfig trace_config_proto;
+ PERFETTO_DLOG("Parsing TraceConfig, %zu bytes", trace_config_raw.size());
+ bool parsed = trace_config_proto.ParseFromString(trace_config_raw);
+ if (!parsed) {
+ PERFETTO_ELOG("Could not parse TraceConfig proto from stdin");
+ return 1;
+ }
+ trace_config_.reset(new TraceConfig());
+ trace_config_->FromProto(trace_config_proto);
+ trace_config_raw.clear();
+
+ consumer_endpoint_ = ConsumerIPCClient::Connect(PERFETTO_CONSUMER_SOCK_NAME,
+ this, &task_runner_);
+
+#if defined(PERFETTO_BUILD_WITH_ANDROID)
+ android::sp<android::Looper> looper(android::Looper::prepare(0 /* opts */));
+ while (true) {
+ looper->pollAll(-1 /* timeoutMillis */);
+ }
+#else // defined(PERFETTO_BUILD_WITH_ANDROID)
+ task_runner_.Run();
+#endif // defined(PERFETTO_BUILD_WITH_ANDROID)
+ return did_receive_full_trace_ ? 0 : 1;
+} // namespace perfetto
+
+void PerfettoCmd::OnConnect() {
+ PERFETTO_LOG(
+ "Connected to the Perfetto traced service, starting tracing for %d ms",
+ trace_config_->duration_ms());
+ PERFETTO_DCHECK(trace_config_);
+ consumer_endpoint_->EnableTracing(*trace_config_);
+ task_runner_.PostDelayedTask(std::bind(&PerfettoCmd::OnStopTraceTimer, this),
+ trace_config_->duration_ms());
+}
+
+void PerfettoCmd::OnDisconnect() {
+ PERFETTO_LOG("Disconnected from the Perfetto traced service");
+ task_runner_.Quit();
+}
+
+void PerfettoCmd::OnStopTraceTimer() {
+ PERFETTO_LOG("Timer expired, disabling tracing and collecting results");
+ consumer_endpoint_->DisableTracing();
+ consumer_endpoint_->ReadBuffers();
+}
+
+void PerfettoCmd::OnTraceData(std::vector<TracePacket> packets, bool has_more) {
+ PERFETTO_LOG("Received packet %d", has_more);
+ for (TracePacket& packet : packets) {
+ for (const Chunk& chunk : packet) {
+ trace_out_stream_.write(reinterpret_cast<const char*>(chunk.start),
+ chunk.size);
+ }
+ }
+ if (has_more)
+ return;
+
+ // Reached end of trace.
+ long bytes_written = trace_out_stream_.tellp();
+ trace_out_stream_.close();
+ std::string tmp_path = trace_out_path_ + ".tmp";
+ PERFETTO_CHECK(rename(tmp_path.c_str(), trace_out_path_.c_str()) == 0);
+ did_receive_full_trace_ = true;
+ PERFETTO_ILOG("Wrote %ld bytes into %s", bytes_written,
+ trace_out_path_.c_str());
+ consumer_endpoint_->FreeBuffers();
+ task_runner_.Quit();
+}
+
+int __attribute__((visibility("default")))
+PerfettoCmdMain(int argc, char** argv) {
+ perfetto::PerfettoCmd consumer_cmd;
+ return consumer_cmd.Main(argc, argv);
+}
+
+} // namespace perfetto
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index 3c7b96b..79416d4 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -26,6 +26,7 @@
# libraries are also mapped to their Android equivalents -- see |builtin_deps|.
import argparse
+import errno
import json
import os
import re
@@ -35,10 +36,12 @@
# Default targets to translate to the blueprint file.
default_targets = [
+ '//:libtraced_shared',
+ '//:perfetto',
'//:perfetto_tests',
+ '//:perfetto',
'//:traced',
'//:traced_probes',
- '//:libtraced_shared',
'//src/tracing:consumer_cmd',
]
@@ -47,7 +50,7 @@
target_initrc = {} # TODO(primiano): populate in upcoming CLs.
# Arguments for the GN output directory.
-gn_args = 'target_os="android" target_cpu="arm" is_debug=false'
+gn_args = 'target_os="android" target_cpu="arm" is_debug=false build_with_android=true'
# All module names are prefixed with this string to avoid collisions.
module_prefix = 'perfetto_'
@@ -56,6 +59,7 @@
library_whitelist = [
'android',
'log',
+ 'utils',
]
# Name of the module which settings such as compiler flags for all other
@@ -65,6 +69,9 @@
# Location of the project in the Android source tree.
tree_path = 'external/perfetto'
+# Compiler flags which are passed through to the blueprint.
+cflag_whitelist = r'^-DPERFETTO.*$'
+
def enable_gmock(module):
module.static_libs.append('libgmock')
@@ -436,6 +443,9 @@
# Don't try to inject library/source dependencies into genrules because
# they are not compiled in the traditional sense.
if module.type != 'genrule':
+ for flag in target.get('cflags', []):
+ if re.match(cflag_whitelist, flag):
+ module.cflags.append(flag)
module.defaults = [defaults_module]
apply_module_dependency(blueprint, desc, module, target_name)
for dep in resolve_dependencies(desc, target_name):