Skip to content
5 changes: 5 additions & 0 deletions include/perfetto/public/protos/config/trace_config.pzc.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,11 @@ PERFETTO_PB_FIELD(perfetto_protos_TraceConfig,
bool,
no_flush_before_write_into_file,
42);
PERFETTO_PB_FIELD(perfetto_protos_TraceConfig,
VARINT,
bool,
persist_trace_after_reboot,
43);

PERFETTO_PB_MSG(perfetto_protos_TraceConfig_SessionSemaphore);
PERFETTO_PB_FIELD(perfetto_protos_TraceConfig_SessionSemaphore,
Expand Down
5 changes: 5 additions & 0 deletions perfetto.rc
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ on property:persist.traced.enable=1
# Traces in this directory are only accessed by system server
mkdir /data/misc/perfetto-traces/profiling 0777 root shell

# TODO(ktimofeev): add a comment about persistent traces locations
mkdir /data/misc/perfetto-traces/persistent 0777 root shell

# This directory allows shell to save configs file in a place where the
# perfetto cmdline client can read then. /data/local/tmp/ isn't safe because
# too many other domains can write into that. See b/170404111.
Expand All @@ -103,6 +106,8 @@ on property:persist.traced.enable=2
# Reset the Perfetto guard rail state on boot:
on post-fs-data
rm /data/misc/perfetto-traces/.guardraildata
exec -- /system/bin/perfetto --upload-after-reboot


#############################################################################
# perfetto_trace_on_boot - Starts a perfetto trace on boot
Expand Down
6 changes: 5 additions & 1 deletion protos/perfetto/config/perfetto_config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4202,7 +4202,7 @@ message DataSourceConfig {
// It contains the general config for the logging buffer(s) and the configs for
// all the data source being enabled.
//
// Next id: 43.
// Next id: 44.
message TraceConfig {
message BufferConfig {
optional uint32 size_kb = 1;
Expand Down Expand Up @@ -4954,6 +4954,10 @@ message TraceConfig {
// Introduced in: perfetto v53.
// Supported on: Android 25Q4+.
optional bool no_flush_before_write_into_file = 42;

// TODO(ktimofeev): add documentation about this flag.
// TODO(ktimofeev): figure out better name?
optional bool persist_trace_after_reboot = 43;
}

// End of protos/perfetto/config/trace_config.proto
6 changes: 5 additions & 1 deletion protos/perfetto/config/trace_config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import "protos/perfetto/config/priority_boost/priority_boost_config.proto";
// It contains the general config for the logging buffer(s) and the configs for
// all the data source being enabled.
//
// Next id: 43.
// Next id: 44.
message TraceConfig {
message BufferConfig {
optional uint32 size_kb = 1;
Expand Down Expand Up @@ -779,4 +779,8 @@ message TraceConfig {
// Introduced in: perfetto v53.
// Supported on: Android 25Q4+.
optional bool no_flush_before_write_into_file = 42;

// TODO(ktimofeev): add documentation about this flag.
// TODO(ktimofeev): figure out better name?
optional bool persist_trace_after_reboot = 43;
}
6 changes: 5 additions & 1 deletion protos/perfetto/trace/perfetto_trace.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4202,7 +4202,7 @@ message DataSourceConfig {
// It contains the general config for the logging buffer(s) and the configs for
// all the data source being enabled.
//
// Next id: 43.
// Next id: 44.
message TraceConfig {
message BufferConfig {
optional uint32 size_kb = 1;
Expand Down Expand Up @@ -4954,6 +4954,10 @@ message TraceConfig {
// Introduced in: perfetto v53.
// Supported on: Android 25Q4+.
optional bool no_flush_before_write_into_file = 42;

// TODO(ktimofeev): add documentation about this flag.
// TODO(ktimofeev): figure out better name?
optional bool persist_trace_after_reboot = 43;
}

// End of protos/perfetto/config/trace_config.proto
Expand Down
97 changes: 80 additions & 17 deletions src/perfetto_cmd/perfetto_cmd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
#include "perfetto/tracing/core/forward_decls.h"
#include "perfetto/tracing/core/trace_config.h"
#include "perfetto/tracing/default_socket.h"
#include "protos/perfetto/common/data_source_descriptor.gen.h"
#include "src/android_stats/perfetto_atoms.h"
#include "src/android_stats/statsd_logging_helper.h"
#include "src/perfetto_cmd/bugreport_path.h"
Expand All @@ -80,9 +79,11 @@
#include "src/perfetto_cmd/trigger_producer.h"
#include "src/trace_config_utils/txt_to_pb.h"

#include "protos/perfetto/common/data_source_descriptor.gen.h"
#include "protos/perfetto/common/ftrace_descriptor.gen.h"
#include "protos/perfetto/common/tracing_service_state.gen.h"
#include "protos/perfetto/common/track_event_descriptor.gen.h"
#include "protos/perfetto/config/trace_config.gen.h"

// For dup() (and _setmode() on windows).
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
Expand Down Expand Up @@ -176,19 +177,20 @@ Light configuration flags: (only when NOT using -c/--config)
ATRACE_CAT : Record ATRACE_CAT (e.g. wm) (Android only)

Statsd-specific and other Android-only flags:
--alert-id : ID of the alert that triggered this trace.
--config-id : ID of the triggering config.
--config-uid : UID of app which registered the config.
--subscription-id : ID of the subscription that triggered this trace.
--upload : Upload trace.
--dropbox TAG : DEPRECATED: Use --upload instead
TAG should always be set to 'perfetto'.
--save-for-bugreport : If a trace with bugreport_score > 0 is running, it
saves it into a file. Outputs the path when done.
--no-guardrails : Ignore guardrails triggered when using --upload
(testing only).
--reset-guardrails : Resets the state of the guardails and exits
(testing only).
--alert-id : ID of the alert that triggered this trace.
--config-id : ID of the triggering config.
--config-uid : UID of app which registered the config.
--subscription-id : ID of the subscription that triggered this trace.
--upload : Upload trace.
--upload-after-reboot : TODO(ktimofeev): add description
--dropbox TAG : DEPRECATED: Use --upload instead
TAG should always be set to 'perfetto'.
--save-for-bugreport : If a trace with bugreport_score > 0 is running, it
saves it into a file. Outputs the path when done.
--no-guardrails : Ignore guardrails triggered when using --upload
(testing only).
--reset-guardrails : Resets the state of the guardails and exits
(testing only).

Detach mode. DISCOURAGED, read https://perfetto.dev/docs/concepts/detached-mode
--detach=key : Detach from the tracing session with the given key.
Expand Down Expand Up @@ -219,6 +221,7 @@ std::optional<int> PerfettoCmd::ParseCmdlineAndMaybeDaemonize(int argc,
OPT_PBTXT_CONFIG,
OPT_DROPBOX,
OPT_UPLOAD,
OPT_UPLOAD_AFTER_REBOOT,
OPT_IGNORE_GUARDRAILS,
OPT_DETACH,
OPT_ATTACH,
Expand All @@ -242,6 +245,7 @@ std::optional<int> PerfettoCmd::ParseCmdlineAndMaybeDaemonize(int argc,
{"no-guardrails", no_argument, nullptr, OPT_IGNORE_GUARDRAILS},
{"txt", no_argument, nullptr, OPT_PBTXT_CONFIG},
{"upload", no_argument, nullptr, OPT_UPLOAD},
{"upload-after-reboot", no_argument, nullptr, OPT_UPLOAD_AFTER_REBOOT},
{"dropbox", required_argument, nullptr, OPT_DROPBOX},
{"alert-id", required_argument, nullptr, OPT_ALERT_ID},
{"config-id", required_argument, nullptr, OPT_CONFIG_ID},
Expand Down Expand Up @@ -398,6 +402,16 @@ std::optional<int> PerfettoCmd::ParseCmdlineAndMaybeDaemonize(int argc,
#endif
}

if (option == OPT_UPLOAD_AFTER_REBOOT) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
upload_after_reboot_flag_ = true;
continue;
#else
PERFETTO_ELOG("--upload-after-reboot is only supported on Android");
return 1;
#endif
}

if (option == OPT_DROPBOX) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
PERFETTO_CHECK(optarg);
Expand Down Expand Up @@ -536,6 +550,14 @@ std::optional<int> PerfettoCmd::ParseCmdlineAndMaybeDaemonize(int argc,
return 1;
}

if (upload_after_reboot_flag_ &&
(bugreport_ || clone_all_bugreport_traces_ || is_attach() ||
is_detach() || query_service_ || has_config_options ||
background_wait_)) {
PERFETTO_ELOG("--upload-after-reboot cannot take any other argument");
return 1;
}

if ((bugreport_ || clone_all_bugreport_traces_) &&
(is_attach() || is_detach() || query_service_ || has_config_options ||
background_wait_)) {
Expand Down Expand Up @@ -572,8 +594,9 @@ std::optional<int> PerfettoCmd::ParseCmdlineAndMaybeDaemonize(int argc,

bool parsed = false;
bool cfg_could_be_txt = false;
const bool will_trace_or_trigger =
!is_attach() && !query_service_ && !clone_all_bugreport_traces_;
const bool will_trace_or_trigger = !is_attach() && !query_service_ &&
!clone_all_bugreport_traces_ &&
!upload_after_reboot_flag_;
if (!will_trace_or_trigger) {
if ((!trace_config_raw.empty() || has_config_options)) {
PERFETTO_ELOG("Cannot specify a trace config with this option");
Expand Down Expand Up @@ -761,6 +784,10 @@ std::optional<int> PerfettoCmd::ParseCmdlineAndMaybeDaemonize(int argc,
trace_config_.reset(new TraceConfig());
}

if (upload_flag_ && trace_config_->persist_trace_after_reboot()) {
trace_config_->set_write_into_file(true);
}

bool open_out_file = true;
if (!will_trace_or_trigger) {
open_out_file = false;
Expand Down Expand Up @@ -892,6 +919,26 @@ int PerfettoCmd::ConnectToServiceRunAndMaybeNotify() {
}

int PerfettoCmd::ConnectToServiceAndRun() {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
if (upload_after_reboot_flag_) {
std::string traced_prop = base::GetAndroidProp("persist.traced.enable");
std::string boot_prop = base::GetAndroidProp("sys.boot_completed");
PERFETTO_LOG(
"ConnectToServiceAndRun, upload_after_reboot, traced_prop: %s, "
"boot_prop: %s",
traced_prop.c_str(), boot_prop.c_str());
// Doesn't actually connect to service.
ReportAllPersistentTracesToAndroidFrameworkOrCrash();
return 0;
}
#endif

{
std::string traced_prop = base::GetAndroidProp("persist.traced.enable");
std::string boot_prop = base::GetAndroidProp("sys.boot_completed");
PERFETTO_LOG("ConnectToServiceAndRun, traced_prop: %s, boot_prop: %s",
traced_prop.c_str(), boot_prop.c_str());
}
// If we are just activating triggers then we don't need to rate limit,
// connect as a consumer or run the trace. So bail out after processing all
// the options.
Expand Down Expand Up @@ -1205,6 +1252,9 @@ void PerfettoCmd::FinalizeTraceAndExit() {
#endif
} else if (report_to_android_framework_) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
if (trace_config_->persist_trace_after_reboot()) {
unlink(trace_out_path_.c_str());
}
ReportTraceToAndroidFrameworkOrCrash();
#endif
} else {
Expand All @@ -1226,7 +1276,20 @@ bool PerfettoCmd::OpenOutputFile() {
base::ScopedFile fd;
if (trace_out_path_.empty()) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
fd = CreateUnlinkedTmpFile();
if (trace_config_->persist_trace_after_reboot()) {
auto trace_file_or_error =
CreatePersistentTraceFile(trace_config_->unique_session_name());
if (trace_file_or_error.ok()) {
fd = std::move(trace_file_or_error->fd);
trace_out_path_ = trace_file_or_error->path;
} else {
PERFETTO_ELOG("Failed to create a persistent trace file: %s",
trace_file_or_error.status().c_message());
return false;
}
} else {
fd = CreateUnlinkedTmpFile();
}
#endif
} else if (trace_out_path_ == "-") {
fd.reset(dup(fileno(stdout)));
Expand Down
16 changes: 15 additions & 1 deletion src/perfetto_cmd/perfetto_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "perfetto/ext/base/pipe.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/scoped_mmap.h"
#include "perfetto/ext/base/status_or.h"
#include "perfetto/ext/base/thread_task_runner.h"
#include "perfetto/ext/base/uuid.h"
#include "perfetto/ext/base/weak_ptr.h"
Expand Down Expand Up @@ -136,12 +137,24 @@ class PerfettoCmd : public Consumer {
const SnapshotTriggerInfo& trigger);

#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
static base::ScopedFile CreateUnlinkedTmpFile();
static std::optional<TraceConfig> ParseTraceConfigFromMmapedTrace(
base::ScopedMmap mmapped_trace);
static base::ScopedFile CreateUnlinkedTmpFile();
struct PersistentTraceFile {
base::ScopedFile fd;
std::string path;
};
static base::StatusOr<PersistentTraceFile> CreatePersistentTraceFile(
const std::string& unique_session_name);
void SaveTraceIntoIncidentOrCrash();
void SaveOutputToIncidentTraceOrCrash();
void ReportTraceToAndroidFrameworkOrCrash();

public:
static std::vector<base::ScopedFile> UnlinkAndGetAllTracesToUpload();
static void ReportAllPersistentTracesToAndroidFrameworkOrCrash();

private:
#endif
void LogUploadEvent(PerfettoStatsdAtom atom);
void LogUploadEvent(PerfettoStatsdAtom atom, const std::string& trigger_name);
Expand Down Expand Up @@ -178,6 +191,7 @@ class PerfettoCmd : public Consumer {
bool background_wait_ = false;
bool ignore_guardrails_ = false;
bool upload_flag_ = false;
bool upload_after_reboot_flag_ = false;
bool connected_ = false;
std::string uuid_;
std::optional<TracingSessionID> clone_tsid_{};
Expand Down
Loading
Loading