blob: ffee900e715bc4d76cf09837fc831a185e808ece [file] [log] [blame]
/*
* 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.
*/
syntax = "proto2";
package perfetto.protos;
import "protos/perfetto/common/builtin_clock.proto";
import "protos/perfetto/config/data_source_config.proto";
// The overall config that is used when starting a new tracing session through
// ProducerPort::StartTracing().
// It contains the general config for the logging buffer(s) and the configs for
// all the data source being enabled.
//
// Next id: 38.
message TraceConfig {
message BufferConfig {
optional uint32 size_kb = 1;
// |page_size|, now deprecated.
reserved 2;
// |optimize_for|, now deprecated.
reserved 3;
enum FillPolicy {
UNSPECIFIED = 0;
// Default behavior. The buffer operates as a conventional ring buffer.
// If the writer is faster than the reader (or if the reader reads only
// after tracing is stopped) newly written packets will overwrite old
// packets.
RING_BUFFER = 1;
// Behaves like RING_BUFFER as long as there is space in the buffer or
// the reader catches up with the writer. As soon as the writer hits
// an unread chunk, it stops accepting new data in the buffer.
DISCARD = 2;
}
optional FillPolicy fill_policy = 4;
// When true the buffer is moved (rather than copied) onto the cloned
// session, and an empty buffer of the same size is allocated in the source
// tracing session. This feature will likely get deprecated in the future.
// It been introduced mainly to support the surfaceflinger snapshot dump
// for bugreports, where SF can dumps O(400MB) into the bugreport trace. In
// that case we don't want to retain another in-memory copy of the buffer.
optional bool transfer_on_clone = 5;
// Used in conjuction with transfer_on_clone. When true the buffer is
// cleared before issuing the Flush(reason=kTraceClone). This is to ensure
// that if the data source took too long to write the data in a previous
// clone-related flush, we don't end up with a mixture of leftovers from
// the previous write and new data.
optional bool clear_before_clone = 6;
}
repeated BufferConfig buffers = 1;
message DataSource {
// Filters and data-source specific config. It contains also the unique name
// of the data source, the one passed in the DataSourceDescriptor when they
// register on the service.
optional protos.DataSourceConfig config = 1;
// Optional. If multiple producers (~processes) expose the same data source
// and either |producer_name_filter| or |producer_name_regex_filter| is set,
// the data source is enabled only for producers whose names match any of
// the filters.
// |producer_name_filter| has to be an exact match, while
// |producer_name_regex_filter| is a regular expression.
// This allows to enable a data source only for specific processes.
// The "repeated" fields have OR semantics: specifying a filter ["foo",
// "bar"] will enable data sources on both "foo" and "bar" (if they exist).
repeated string producer_name_filter = 2;
repeated string producer_name_regex_filter = 3;
}
repeated DataSource data_sources = 2;
// Config for disabling builtin data sources in the tracing service.
message BuiltinDataSource {
// Disable emitting clock timestamps into the trace.
optional bool disable_clock_snapshotting = 1;
// Disable echoing the original trace config in the trace.
optional bool disable_trace_config = 2;
// Disable emitting system info (build fingerprint, cpuinfo, etc).
optional bool disable_system_info = 3;
// Disable emitting events for data-source state changes (e.g. the marker
// for all data sources having ACKed the start of the trace).
optional bool disable_service_events = 4;
// The authoritative clock domain for the trace. Defaults to BOOTTIME. See
// also ClockSnapshot's primary_trace_clock. The configured value is written
// into the trace as part of the ClockSnapshots emitted by the service.
// Trace processor will attempt to translate packet/event timestamps from
// various data sources (and their chosen clock domains) to this domain
// during import. Added in Android R.
optional BuiltinClock primary_trace_clock = 5;
// Time interval in between snapshotting of sync markers, clock snapshots,
// stats, and other periodic service-emitted events. Note that the service
// only keeps track of the first and the most recent snapshot until
// ReadBuffers() is called.
optional uint32 snapshot_interval_ms = 6;
// Hints to the service that a suspend-aware (i.e. counting time in suspend)
// clock should be used for periodic snapshots of service-emitted events.
// This means, if a snapshot *should* have happened during suspend, it will
// happen immediately after the device resumes.
//
// Choosing a clock like this is done on best-effort basis; not all
// platforms (e.g. Windows) expose a clock which can be used for periodic
// tasks counting suspend. If such a clock is not available, the service
// falls back to the best-available alternative.
//
// Introduced in Android S.
// TODO(lalitm): deprecate this in T and make this the default if nothing
// crashes in S.
optional bool prefer_suspend_clock_for_snapshot = 7;
// Disables the reporting of per-trace-writer histograms in TraceStats.
optional bool disable_chunk_usage_histograms = 8;
}
optional BuiltinDataSource builtin_data_sources = 20;
// If specified, the trace will be stopped |duration_ms| after starting.
// This does *not* count the time the system is suspended, so we will run
// for duration_ms of system activity, not wall time.
//
// However in case of traces with triggers, see
// TriggerConfig.trigger_timeout_ms instead.
optional uint32 duration_ms = 3;
// If true, tries to use CLOCK_BOOTTIME for duration_ms rather than
// CLOCK_MONOTONIC (which doesn't count time in suspend). Supported only on
// Linux/Android, no-op on other platforms. This is used when dealing with
// long (e.g. 24h) traces, where suspend can inflate them to weeks of
// wall-time, making them more likely to hit device reboots (and hence loss).
// This option also changes consistently the semantic of
// TrigerConfig.stop_delay_ms.
optional bool prefer_suspend_clock_for_duration = 36;
// This is set when --dropbox is passed to the Perfetto command line client
// and enables guardrails that limit resource usage for traces requested
// by statsd.
optional bool enable_extra_guardrails = 4;
enum LockdownModeOperation {
LOCKDOWN_UNCHANGED = 0;
LOCKDOWN_CLEAR = 1;
LOCKDOWN_SET = 2;
}
// Reject producers that are not running under the same UID as the tracing
// service.
optional LockdownModeOperation lockdown_mode = 5;
message ProducerConfig {
// Identifies the producer for which this config is for.
optional string producer_name = 1;
// Specifies the preferred size of the shared memory buffer. If the size is
// larger than the max size, the max will be used. If it is smaller than
// the page size or doesn't fit pages evenly into it, it will fall back to
// the size specified by the producer or finally the default shared memory
// size.
optional uint32 shm_size_kb = 2;
// Specifies the preferred size of each page in the shared memory buffer.
// Must be an integer multiple of 4K.
optional uint32 page_size_kb = 3;
}
repeated ProducerConfig producers = 6;
// Contains statsd-specific metadata about an alert associated with the trace.
message StatsdMetadata {
// The identifier of the alert which triggered this trace.
optional int64 triggering_alert_id = 1;
// The uid which registered the triggering configuration with statsd.
optional int32 triggering_config_uid = 2;
// The identifier of the config which triggered the alert.
optional int64 triggering_config_id = 3;
// The identifier of the subscription which triggered this trace.
optional int64 triggering_subscription_id = 4;
}
// Statsd-specific metadata.
optional StatsdMetadata statsd_metadata = 7;
// When true && |output_path| is empty, the EnableTracing() request must
// provide a file descriptor. The service will then periodically read packets
// out of the trace buffer and store it into the passed file.
// If |output_path| is not empty no fd should be passed, the service
// will create a new file and write into that (see comment below).
optional bool write_into_file = 8;
// This must point to a non-existing file. If the file exists the service
// will NOT overwrite and will fail instead as a security precaution.
// On Android, when this is used with the system traced, the path must be
// within /data/misc/perfetto-traces/ or the trace will fail.
// This option has been introduced in Android R. Before R write_into_file
// can be used only with the "pass a file descriptor over IPC" mode.
optional string output_path = 29;
// Optional. If non-zero tunes the write period. A min value of 100ms is
// enforced (i.e. smaller values are ignored).
optional uint32 file_write_period_ms = 9;
// Optional. When non zero the periodic write stops once at most X bytes
// have been written into the file. Tracing is disabled when this limit is
// reached, even if |duration_ms| has not been reached yet.
optional uint64 max_file_size_bytes = 10;
// Contains flags which override the default values of the guardrails inside
// Perfetto.
message GuardrailOverrides {
// Override the default limit (in bytes) for uploading data to server within
// a 24 hour period.
// On R-, this override only affected userdebug builds. Since S, it also
// affects user builds.
optional uint64 max_upload_per_day_bytes = 1;
// Overrides the guardrail for maximum trace buffer size.
// Available on U+
optional uint32 max_tracing_buffer_size_kb = 2;
}
optional GuardrailOverrides guardrail_overrides = 11;
// When true, data sources are not started until an explicit call to
// StartTracing() on the consumer port. This is to support early
// initialization and fast trace triggering. This can be used only when the
// Consumer explicitly triggers the StartTracing() method.
// This should not be used in a remote trace config via statsd, doing so will
// result in a hung trace session.
optional bool deferred_start = 12;
// When set, it periodically issues a Flush() to all data source, forcing them
// to commit their data into the tracing service. This can be used for
// quasi-real-time streaming mode and to guarantee some partial ordering of
// events in the trace in windows of X ms.
optional uint32 flush_period_ms = 13;
// Wait for this long for producers to acknowledge flush requests.
// Default 5s.
optional uint32 flush_timeout_ms = 14;
// Wait for this long for producers to acknowledge stop requests.
// Default 5s.
optional uint32 data_source_stop_timeout_ms = 23;
// |disable_clock_snapshotting| moved.
reserved 15;
// Android-only. If set, sends an intent to the Traceur system app when the
// trace ends to notify it about the trace readiness.
optional bool notify_traceur = 16;
// This field was introduced in Android S.
// Android-only. If set to a value > 0, marks the trace session as a candidate
// for being attached to a bugreport. This field effectively acts as a z-index
// for bugreports. When Android's dumpstate runs perfetto
// --save-for-bugreport, traced will pick the tracing session with the highest
// score (score <= 0 is ignored) and:
// On Android S, T: will steal its contents, save the trace into
// a known path and stop prematurely.
// On Android U+: will create a read-only snapshot and save that into a known
// path, without stoppin the original tracing session.
// When this field is set the tracing session becomes eligible to be cloned
// by other UIDs.
optional int32 bugreport_score = 30;
// Triggers allow producers to start or stop the tracing session when an event
// occurs.
//
// For example if we are tracing probabilistically, most traces will be
// uninteresting. Triggers allow us to keep only the interesting ones such as
// those traces during which the device temperature reached a certain
// threshold. In this case the producer can activate a trigger to keep
// (STOP_TRACING) the trace, otherwise it can also begin a trace
// (START_TRACING) because it knows something is about to happen.
message TriggerConfig {
enum TriggerMode {
UNSPECIFIED = 0;
// When this mode is chosen, data sources are not started until one of the
// |triggers| are received. This supports early initialization and fast
// starting of the tracing system. On triggering, the session will then
// record for |stop_delay_ms|. However if no trigger is seen
// after |trigger_timeout_ms| the session will be stopped and no data will
// be returned.
START_TRACING = 1;
// When this mode is chosen, the session will be started via the normal
// EnableTracing() & StartTracing(). If no trigger is ever seen
// the session will be stopped after |trigger_timeout_ms| and no data will
// be returned. However if triggered the trace will stop after
// |stop_delay_ms| and any data in the buffer will be returned to the
// consumer.
STOP_TRACING = 2;
// 3 was taken by CLONE_SNAPSHOT but that has been moved to 4.
// The early implementation of CLONE_SNAPSHOT had various bugs
// (b/290798988, b/290799105) and made it into Android U. The number
// change is to make sure nobody rolls out a config that hits the broken
// behaviour.
reserved 3;
// When this mode is chosen, this causes a snapshot of the current tracing
// session to be created after |stop_delay_ms| while the current tracing
// session continues undisturbed (% an extra flush). This mode can be
// used only when the tracing session is handled by the "perfetto" cmdline
// client (which is true in 90% of cases). Part of the business logic
// necessary for this behavior, and ensuing file handling, lives in
// perfetto_cmd.cc . On other consumers, this causes only a notification
// of the trigger through a CloneTriggerHit ObservableEvent. The custom
// consumer is supposed to call CloneSession() itself after the event.
// Use use_clone_snapshot_if_available=true when targeting older versions
// of perfetto.
CLONE_SNAPSHOT = 4;
// NOTE: CLONE_SNAPSHOT should be used only when we targeting Android V+
// (15+) / Perfetto v38+. A bug in older versions of the tracing service
// might cause indefinitely long tracing sessions (see b/274931668).
}
optional TriggerMode trigger_mode = 1;
// This flag is really a workaround for b/274931668. This is needed only
// when deploying configs to different versions of the tracing service.
// When this is set to true this has the same effect of setting trigger_mode
// to CLONE_SNAPSHOT on newer versions of the service. This boolean has been
// introduced to allow to have configs that use CLONE_SNAPSHOT on newer
// versions of Android and fall back to STOP_TRACING on older versions where
// CLONE_SNAPSHOT did not exist.
// When using this flag, trigger_mode must be set to STOP_TRACING.
optional bool use_clone_snapshot_if_available = 5;
// DEPRECATED, was use_clone_snapshot_if_available in U. See the comment
// around CLONE_SNAPSHOT.
reserved 4;
message Trigger {
// The producer must specify this name to activate the trigger.
optional string name = 1;
// An std::regex that will match the producer that can activate this
// trigger. This is optional. If unset any producers can activate this
// trigger.
optional string producer_name_regex = 2;
// After a trigger is received either in START_TRACING or STOP_TRACING
// mode then the trace will end |stop_delay_ms| after triggering.
// In CLONE_SNAPSHOT mode, this is the delay between the trigger and the
// snapshot.
// If |prefer_suspend_clock_for_duration| is set, the duration will be
// based on wall-clock, counting also time in suspend.
optional uint32 stop_delay_ms = 3;
// Limits the number of traces this trigger can start/stop in a rolling
// 24 hour window. If this field is unset or zero, no limit is applied and
// activiation of this trigger *always* starts/stops the trace.
optional uint32 max_per_24_h = 4;
// A value between 0 and 1 which encodes the probability of skipping a
// trigger with this name. This is useful for reducing the probability
// of high-frequency triggers from dominating trace finaization. If this
// field is unset or zero, the trigger will *never* be skipped. If this
// field is greater than or equal to 1, this trigger will *always* be
// skipped i.e. it will be as if this trigger was never included in the
// first place.
// This probability check is applied *before* any other limits. For
// example, if |max_per_24_h| is also set, first we will check if the
// probability bar is met and only then will we check the |max_per_24_h|
// limit.
optional double skip_probability = 5;
}
// A list of triggers which are related to this configuration. If ANY
// trigger is seen then an action will be performed based on |trigger_mode|.
repeated Trigger triggers = 2;
// Required and must be positive if a TriggerConfig is specified. This is
// how long this TraceConfig should wait for a trigger to arrive. After this
// period of time if no trigger is seen the TracingSession will be cleaned
// up.
optional uint32 trigger_timeout_ms = 3;
}
optional TriggerConfig trigger_config = 17;
// When this is non-empty the perfetto command line tool will ignore the rest
// of this TraceConfig and instead connect to the perfetto service as a
// producer and send these triggers, potentially stopping or starting traces
// that were previous configured to use a TriggerConfig.
repeated string activate_triggers = 18;
// Configuration for trace contents that reference earlier trace data. For
// example, a data source might intern strings, and emit packets containing
// {interned id : string} pairs. Future packets from that data source can then
// use the interned ids instead of duplicating the raw string contents. The
// trace parser will then need to use that interning table to fully interpret
// the rest of the trace.
message IncrementalStateConfig {
// If nonzero, notify eligible data sources to clear their incremental state
// periodically, with the given period. The notification is sent only to
// data sources that have |handles_incremental_state_clear| set in their
// DataSourceDescriptor. The notification requests that the data source
// stops referring to past trace contents. This is particularly useful when
// tracing in ring buffer mode, where it is not exceptional to overwrite old
// trace data.
//
// Warning: this time-based global clearing is likely to be removed in the
// future, to be replaced with a smarter way of sending the notifications
// only when necessary.
optional uint32 clear_period_ms = 1;
}
optional IncrementalStateConfig incremental_state_config = 21;
// Additional guardrail used by the Perfetto command line client.
// On user builds when --dropbox is set perfetto will refuse to trace unless
// this is also set.
// Added in Q.
optional bool allow_user_build_tracing = 19;
// If set the tracing service will ensure there is at most one tracing session
// with this key.
optional string unique_session_name = 22;
// Compress trace with the given method. Best effort.
enum CompressionType {
COMPRESSION_TYPE_UNSPECIFIED = 0;
COMPRESSION_TYPE_DEFLATE = 1;
}
optional CompressionType compression_type = 24;
// Use the legacy codepath that compresses from perfetto_cmd.cc instead of
// using the new codepath that compresses from tracing_service_impl.cc. This
// will be removed in the future.
optional bool compress_from_cli = 37;
// Android-only. Not for general use. If set, saves the trace into an
// incident. This field is read by perfetto_cmd, rather than the tracing
// service. This field must be set when passing the --upload flag to
// perfetto_cmd.
message IncidentReportConfig {
// In this message, either:
// * all of |destination_package|, |destination_class| and |privacy_level|
// must be set.
// * |skip_incidentd| must be explicitly set to true.
optional string destination_package = 1;
optional string destination_class = 2;
// Level of filtering in the requested incident. See |Destination| in
// frameworks/base/core/proto/android/privacy.proto.
optional int32 privacy_level = 3;
// If true, then skips saving the trace to incidentd.
//
// This flag is useful in testing (e.g. Perfetto-statsd integration tests)
// or when we explicitly don't want traces to go to incidentd even when they
// usually would (e.g. configs deployed using statsd but only used for
// inclusion in bugreports using |bugreport_score|).
//
// The motivation for having this flag, instead of just not setting
// |incident_report_config|, is prevent accidents where
// |incident_report_config| is omitted by mistake.
optional bool skip_incidentd = 5;
// If true, do not write the trace into dropbox (i.e. incident only).
// Otherwise, write to both dropbox and incident.
// TODO(lalitm): remove this field as we no longer use Dropbox.
optional bool skip_dropbox = 4 [deprecated = true];
}
optional IncidentReportConfig incident_report_config = 25;
enum StatsdLogging {
STATSD_LOGGING_UNSPECIFIED = 0;
STATSD_LOGGING_ENABLED = 1;
STATSD_LOGGING_DISABLED = 2;
}
// Android-only. Not for general use. If specified, sets the logging to statsd
// of guardrails and checkpoints in the tracing service. perfetto_cmd sets
// this to enabled (if not explicitly set in the config) when specifying
// --upload.
optional StatsdLogging statsd_logging = 31;
// DEPRECATED. Was trace_uuid, use trace_uuid_msb and trace_uuid_lsb instead.
reserved 26;
// An identifier clients can use to tie this trace to other logging.
// DEPRECATED as per v32. See TracePacket.trace_uuid for the authoritative
// Trace UUID. If this field is set, the tracing service will respect the
// requested UUID (i.e. TracePacket.trace_uuid == this field) but only if
// gap-less snapshotting is not used.
optional int64 trace_uuid_msb = 27 [deprecated = true];
optional int64 trace_uuid_lsb = 28 [deprecated = true];
// When set applies a post-filter to the trace contents using the filter
// provided. The filter is applied at ReadBuffers() time and works both in the
// case of IPC readback and write_into_file. This filter can be generated
// using `tools/proto_filter -s schema.proto -F filter_out.bytes` or
// `-T filter_out.escaped_string` (for .pbtx). See go/trace-filtering for
// design.
//
// Introduced in Android S, but it was broken (b/195065199). Reintroduced in
// Android T with a different field number. Updated in Android U with a new
// bytecode version which supports string filtering.
message TraceFilter {
// =========================
// Filter bytecode.
// =========================
// The bytecode as implemented in Android T.
optional bytes bytecode = 1;
// The bytecode as implemented in Android U. Adds support for string
// filtering.
optional bytes bytecode_v2 = 2;
// =========================
// String filtering
// =========================
// The principles and terminology of string filtering is heavily inspired by
// iptables. A "rule" decide how strings should be filtered. Each rule
// contains a "policy" which indicates the algorithm to use for filtering.
// A "chain" is a list of rules which will be sequentially checked against
// each string.
//
// The first rule which applies to the string terminates filtering for that
// string. If no rules apply, the string is left unchanged.
// A policy specifies which algorithm should be used for filtering the
// string.
enum StringFilterPolicy {
SFP_UNSPECIFIED = 0;
// Tries to match the string field against |regex_pattern|. If it
// matches, all matching groups are "redacted" (i.e. replaced with a
// constant string) and filtering is terminated (i.e. no further rules are
// checked). If it doesn't match, the string is left unchanged and the
// next rule in chain is considered.
SFP_MATCH_REDACT_GROUPS = 1;
// Like |SFP_MATCH_REDACT_GROUPS| but tries to do some pre-work before
// checking the regex. Specifically, it tries to parse the string field as
// an atrace tracepoint and checks if the post-tgid field starts with
// |atrace_post_tgid_starts_with|. The regex matching is only performed if
// this check succeeds.
SFP_ATRACE_MATCH_REDACT_GROUPS = 2;
// Tries to match the string field against |regex_pattern|. If it
// matches, filtering is terminated (i.e. no further rules are checked).
// If it doesn't match, the string is left unchanged and the next rule in
// chain is considered.
SFP_MATCH_BREAK = 3;
// Like |SFP_MATCH_BREAK| but tries to do some pre-work before checking
// the regex. Specifically, it tries to parse the string field as an
// atrace tracepoint and checks if the post-tgid field starts with
// |atrace_post_tgid_starts_with|. The regex matching is only performed if
// this check succeeds.
SFP_ATRACE_MATCH_BREAK = 4;
}
// A rule specifies how strings should be filtered.
message StringFilterRule {
// The policy (i.e. algorithm) dictating how strings matching this rule
// should be handled.
optional StringFilterPolicy policy = 1;
// The regex pattern used to match against each string.
optional string regex_pattern = 2;
// The string which should appear after the tgid in atrace tracepoint
// strings.
optional string atrace_payload_starts_with = 3;
}
// A chain is a list of rules which string will be sequentially checked
// against.
message StringFilterChain {
repeated StringFilterRule rules = 1;
}
optional StringFilterChain string_filter_chain = 3;
}
// old field number for trace_filter
reserved 32;
optional TraceFilter trace_filter = 33;
// Android-only. Not for general use. If set, reports the trace to the
// Android framework. This field is read by perfetto_cmd, rather than the
// tracing service. This field must be set when passing the --upload flag to
// perfetto_cmd.
message AndroidReportConfig {
// In this message, either:
// * |reporter_service_package| and |reporter_service_class| must be set.
// * |skip_reporting| must be explicitly set to true.
optional string reporter_service_package = 1;
optional string reporter_service_class = 2;
// If true, then skips reporting the trace to Android framework.
//
// This flag is useful in testing (e.g. Perfetto-statsd integration tests)
// or when we explicitly don't want to report traces to the framework even
// when they usually would (e.g. configs deployed using statsd but only
// used for inclusion in bugreports using |bugreport_score|).
//
// The motivation for having this flag, instead of just not setting
// |framework_report_config|, is prevent accidents where
// |framework_report_config| is omitted by mistake.
optional bool skip_report = 3;
// If true, will direct the Android framework to read the data in trace
// file and pass it to the reporter class over a pipe instead of passing
// the file descriptor directly.
//
// This flag is needed because the Android test framework does not
// currently support priv-app helper apps (in terms of SELinux) and we
// really don't want to add an allow rule for untrusted_app to receive
// trace fds.
//
// Because of this, we instead will direct the framework to create a new
// pipe and pass this to the reporter process instead. As the pipe is
// created by the framework, we won't have any problems with SELinux
// (system_server is already allowed to pass pipe fds, even
// to untrusted apps).
//
// As the name suggests this option *MUST* only be used for testing.
// Note that the framework will reject (and drop) files which are too
// large both for simplicity and to be minimize the amount of data we
// pass to a non-priv app (note that the framework will still check
// manifest permissions even though SELinux permissions are worked around).
optional bool use_pipe_in_framework_for_testing = 4;
}
optional AndroidReportConfig android_report_config = 34;
// If set, delays the start of tracing by a random duration. The duration is
// chosen from a uniform distribution between the specified minimum and
// maximum.
// Note: this delay is implemented by perfetto_cmd *not* by traced so will
// not work if you communicate with traced directly over the consumer API.
// Introduced in Android T.
message CmdTraceStartDelay {
optional uint32 min_delay_ms = 1;
optional uint32 max_delay_ms = 2;
}
optional CmdTraceStartDelay cmd_trace_start_delay = 35;
}