Implement DropBox uploading
This patch adds a --dropbox flag to the perfetto tool for uploading the
recorded trace file into DropBox.
Change-Id: I42ce9080292aa45f2442033a5c1d23c83e6e3855
diff --git a/Android.bp b/Android.bp
index 8db1700..1ecc372 100644
--- a/Android.bp
+++ b/Android.bp
@@ -62,8 +62,10 @@
],
shared_libs: [
"libandroid",
+ "libbinder",
"liblog",
"libprotobuf-cpp-lite",
+ "libservices",
"libutils",
],
static_libs: [
@@ -95,7 +97,9 @@
],
shared_libs: [
"libandroid",
+ "libbinder",
"liblog",
+ "libservices",
"libtraced_shared",
"libutils",
],
@@ -835,7 +839,9 @@
],
shared_libs: [
"libandroid",
+ "libbinder",
"liblog",
+ "libservices",
"libtraced_shared",
"libutils",
],
@@ -855,7 +861,9 @@
],
shared_libs: [
"libandroid",
+ "libbinder",
"liblog",
+ "libservices",
"libtraced_shared",
"libutils",
],
diff --git a/BUILD.gn b/BUILD.gn
index 218a71a..408a682 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -82,7 +82,11 @@
if (build_with_android) {
cflags = [ "-DPERFETTO_BUILD_WITH_ANDROID" ]
deps += [ "src/base:android_task_runner" ]
- libs = [ "utils" ]
+ libs = [
+ "binder",
+ "services",
+ "utils",
+ ]
}
}
diff --git a/src/traced/perfetto_cmd/perfetto_cmd.cc b/src/traced/perfetto_cmd/perfetto_cmd.cc
index c93f7a6..ee6ee9d 100644
--- a/src/traced/perfetto_cmd/perfetto_cmd.cc
+++ b/src/traced/perfetto_cmd/perfetto_cmd.cc
@@ -15,6 +15,7 @@
*/
#include <getopt.h>
+#include <sys/stat.h>
#include <unistd.h>
#include <fstream>
@@ -39,6 +40,7 @@
#if defined(PERFETTO_BUILD_WITH_ANDROID)
#include "perfetto/base/android_task_runner.h"
+#include <android/os/DropBoxManager.h>
#include <utils/Looper.h>
#include <utils/StrongPointer.h>
#endif // defined(PERFETTO_BUILD_WITH_ANDROID)
@@ -47,6 +49,10 @@
// traced service instead of receiving a copy of the chunks and writing them
// from this process.
namespace perfetto {
+namespace {
+const char kTempTraceDir[] = "/data/misc/perfetto-traces";
+const char kDefaultDropBoxTag[] = "perfetto";
+} // namespace
#if defined(PERFETTO_BUILD_WITH_ANDROID)
using PlatformTaskRunner = base::AndroidTaskRunner;
@@ -71,16 +77,19 @@
std::unique_ptr<TraceConfig> trace_config_;
std::ofstream trace_out_stream_;
std::string trace_out_path_;
- bool did_receive_full_trace_ = false;
+ std::string tmp_trace_out_path_;
+ std::string dropbox_tag_;
+ bool did_process_full_trace_ = false;
};
int PerfettoCmd::PrintUsage(const char* argv0) {
fprintf(stderr, R"(Usage: %s
- --background -b : exits immediately and continues the trace in background
- --config -c : /path/to/trace/config/file or - for stdin
- --out -o : /path/to/out/trace/file
- --help
-)", argv0);
+ --background -b : Exits immediately and continues tracing in background
+ --config -c : /path/to/trace/config/file or - for stdin
+ --out -o : /path/to/out/trace/file
+ --dropbox -d TAG : Upload trace into DropBox using tag TAG (default: %s)
+ --help -h
+)", argv0, kDefaultDropBoxTag);
return 1;
}
@@ -91,13 +100,15 @@
{"config", required_argument, 0, 'c'},
{"out", required_argument, 0, 'o'},
{"background", no_argument, 0, 'b'},
+ {"dropbox", optional_argument, 0, 'd'},
{nullptr, 0, nullptr, 0}};
int option_index = 0;
std::string trace_config_raw;
bool background = false;
for (;;) {
- int option = getopt_long(argc, argv, "c:o:b", long_options, &option_index);
+ int option =
+ getopt_long(argc, argv, "c:o:bd::", long_options, &option_index);
if (option == -1)
break; // EOF.
@@ -112,11 +123,11 @@
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_name("com.google.perfetto.ftrace");
+ ds_config->mutable_ftrace_config()->add_event_names("sched_switch");
// TODO(primiano): At the moment this must always be 1.
// Once the target_buffer situation is fixed this can be any number.
ds_config->set_target_buffer(1);
- ds_config->set_trace_category_filters("foo,bar");
test_config.SerializeToString(&trace_config_raw);
} else {
std::ifstream file_stream;
@@ -133,15 +144,19 @@
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;
}
+ if (option == 'd') {
+#if defined(PERFETTO_BUILD_WITH_ANDROID)
+ dropbox_tag_ = optarg ? optarg : kDefaultDropBoxTag;
+ continue;
+#else
+ PERFETTO_ELOG("DropBox is only supported with Android tree builds");
+ return 1;
+#endif
+ }
+
if (option == 'b') {
background = true;
continue;
@@ -149,8 +164,43 @@
return PrintUsage(argv[0]);
}
- if (trace_config_raw.empty())
+ if (!trace_out_path_.empty() && !dropbox_tag_.empty()) {
+ PERFETTO_ELOG(
+ "Can't log to a file (--out) and DropBox (--dropbox) at the same "
+ "time");
+ return 1;
+ }
+
+ if (trace_config_raw.empty() ||
+ (trace_out_path_.empty() && dropbox_tag_.empty())) {
return PrintUsage(argv[0]);
+ }
+
+ if (access(kTempTraceDir, F_OK) == -1 && mkdir(kTempTraceDir, 0770) == -1) {
+ PERFETTO_ELOG("Could not create temporary trace directory: %s",
+ kTempTraceDir);
+ return 1;
+ }
+
+ {
+ tmp_trace_out_path_ = std::string(kTempTraceDir) + "/perfetto-traceXXXXXX";
+ // TODO(skyostil): Use open(O_TMPFILE) + linkat so we don't leave partial
+ // trace files lying around in case of unexpected termination.
+ base::ScopedFile tmp_file(mkstemp(&tmp_trace_out_path_[0]));
+ if (!tmp_file) {
+ PERFETTO_ELOG("Could not create a temporary trace file in %s",
+ kTempTraceDir);
+ return 1;
+ }
+ }
+
+ trace_out_stream_.open(tmp_trace_out_path_,
+ std::ios_base::out | std::ios_base::binary);
+ if (!trace_out_stream_.is_open()) {
+ PERFETTO_ELOG("Could not open %s", tmp_trace_out_path_.c_str());
+ return 1;
+ }
+
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);
@@ -169,16 +219,8 @@
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;
+ return did_process_full_trace_ ? 0 : 1;
} // namespace perfetto
void PerfettoCmd::OnConnect() {
@@ -214,15 +256,33 @@
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();
+
+ long bytes_written = trace_out_stream_.tellp();
+ trace_out_stream_.close();
+ if (!dropbox_tag_.empty()) {
+#if defined(PERFETTO_BUILD_WITH_ANDROID)
+ android::sp<android::os::DropBoxManager> dropbox =
+ new android::os::DropBoxManager();
+ android::binder::Status status =
+ dropbox->addFile(android::String16(dropbox_tag_.c_str()),
+ tmp_trace_out_path_, 0 /* flags */);
+ unlink(tmp_trace_out_path_.c_str());
+ if (!status.isOk()) {
+ PERFETTO_ELOG("DropBox upload failed: %s", status.toString8().c_str());
+ return;
+ }
+ PERFETTO_ILOG("Uploaded %ld bytes into DropBox with tag %s", bytes_written,
+ dropbox_tag_.c_str());
+#endif // defined(PERFETTO_BUILD_WITH_ANDROID)
+ } else {
+ PERFETTO_CHECK(
+ rename(tmp_trace_out_path_.c_str(), trace_out_path_.c_str()) == 0);
+ PERFETTO_ILOG("Wrote %ld bytes into %s", bytes_written,
+ trace_out_path_.c_str());
+ }
+ did_process_full_trace_ = true;
}
int __attribute__((visibility("default")))
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index 6b3b126..83ca6a3 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -58,7 +58,9 @@
# Shared libraries which are directly translated to Android system equivalents.
library_whitelist = [
'android',
+ 'binder',
'log',
+ 'services',
'utils',
]