/*
 * 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/common/semantic_type.proto";
import "protos/perfetto/config/data_source_config.proto";
import "protos/perfetto/config/priority_boost/priority_boost_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: 47.
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 conjunction 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;

    // Optional name for this buffer. If set, data sources can reference this
    // buffer by name using |target_buffer_name| in DataSourceConfig instead of
    // using the buffer index. Buffer names must be unique within a tracing
    // session. This provides a more human-readable and less error-prone way to
    // configure which buffer a data source writes to.
    optional string name = 7;

    // When true, uses the experimental TraceBufferV2 implementation for this
    // buffer. This is for testing purposes only and may be removed in future
    // versions.
    enum ExperimentalMode {
      // Use the default V1 implementation.
      MODE_UNSPECIFIED = 0;

      // Use TraceBufferV2.
      TRACE_BUFFER_V2 = 1;

      // Use both V1 and V2 in shadow mode. Data is written to both buffers,
      // but only V1 data is returned. Comparison stats are reported to
      // validate V2 returns equivalent data.
      TRACE_BUFFER_V2_SHADOW_MODE = 2;
    }
    optional ExperimentalMode experimental_mode = 8;
  }
  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;

    // Filter by machine names. The name of a machine is determined by the
    // PERFETTO_MACHINE_NAME env variable. In Android systems, if the env
    // variable is not set then the
    // persist.traced_relay.machine_name system property is used. If the
    // sysprop isn't set or not in an Android system, then the machine name by
    // default is set to the utsname sysname (e.g. Linux), which can be obtained
    // via the 'uname -s' command. As a convenience, one can use "host" to refer
    // to the host machine, which is the machine running traced.
    repeated string machine_name_filter = 4;
  }
  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;

    // Disable emitting extension descriptors into the trace.
    optional bool disable_extension_descriptors = 9;
  }
  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
  // TriggerConfig.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.
    // In 24Q3+ (V+), this override is a noop because upload guardrail logic
    // was removed from Perfetto.
    optional uint64 max_upload_per_day_bytes = 1 [deprecated = true];

    // 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.
  //
  // Warning: Perfetto automatically handles periodic flushing so in most
  // scenarios setting this field is not needed. High frequency flushing can
  // significantly impact performance.
  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;

  // When set, defines name of the file that will be saved under
  // /data/misc/perfetto-traces/bugreport/ when using --save-all-for-bugreport.
  // If omitted, traces will be named systrace.pftrace, systrace_1.pftrace, etc,
  // starting from the highest `bugreport_score`.
  // Introduced in v42 / Android V.
  optional string bugreport_filename = 38;

  // 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;

  // No longer needed as we unconditionally allow tracing on user builds.
  optional bool allow_user_build_tracing = 19 [deprecated = true];

  // 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;

  // DEPRECATED, was compress_from_cli.
  reserved 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;

      // Tries to repeatedly search (i.e. find substrings of) the string field
      // with |regex_pattern|. For each match, redacts any matching groups (i.e.
      // replaced with a constant string). Once there are no further matches,
      // filtering is terminated (i.e. no further rules are checked).
      //
      // Note that this is policy is a "search" policy not a "match" policy
      // unlike the above policies:
      //  * Match policies require matching the full string i.e. there is an
      //    implicit leading `^` and trailing `$`.
      //  * Search policies perform repeated partial matching of the string
      //    e.g.
      //      - String: `foo=aaa,bar=123,foo=bbb,baz=456`
      //      - Pattern: `foo=(\d+)`
      //      - Output: `foo=P6O,bar=123,foo=P6O,baz=456`
      //    where P6O is the redaction string
      //
      // All of this is only performed after some pre-work where we try to parse
      // the string field as an atrace tracepoint and check if the post-tgid
      // field starts with |atrace_post_tgid_starts_with|.
      //
      // If there are no partial matches, the string is left unchanged and the
      // next rule in chain is considered.
      SFP_ATRACE_REPEATED_SEARCH_REDACT_GROUPS = 5;
    }

    // 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;

      // Optional name for the rule. When merging chains (e.g. via
      // string_filter_chain_v54), rules with matching names in the newer chain
      // will overwrite rules in the base chain. Rules without a name (empty or
      // unset) are always treated as distinct and will be appended.
      // See /rfcs/0011-subset-string-filter-rules.md for design details.
      // Introduced in: Perfetto v54.
      optional string name = 4;

      // The semantic types this rule applies to.
      //
      // SEMANTIC_TYPE_UNSPECIFIED (0) is treated as its own distinct category:
      // - If empty, the rule applies only to fields with UNSPECIFIED type.
      // - If non-empty, the rule applies only to fields whose semantic type
      //   is explicitly listed. To match UNSPECIFIED fields, you must include
      //   SEMANTIC_TYPE_UNSPECIFIED in the list.
      //
      // Examples:
      //   semantic_type: []           -> matches only UNSPECIFIED fields
      //   semantic_type: [ATRACE]     -> matches only ATRACE fields
      //   semantic_type: [UNSPECIFIED, ATRACE] -> matches both
      //
      // See /rfcs/0011-subset-string-filter-rules.md for design details.
      // Introduced in: Perfetto v54.
      repeated SemanticType semantic_type = 5;
    }

    // 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;

    // Bytecode overlay for Perfetto v54+. This overlay is applied on top of
    // bytecode_v2 to upgrade specific simple fields to new values. Old Perfetto
    // versions ignore this field; new versions apply it.
    //
    // The motivation for this is that adding new opcodes in a backwards
    // compatible way while also minimizing config size is hard. Instead, the
    // overlay mechanism allows us to "patch" specific fields in the original
    // bytecode_v2 with new semantics.
    //
    // See RFC 0011-subset-string-filter-rules.md for more info.
    //
    // Note:
    // Unlike bytecode_v2 (which uses implicit message indices via EndOfMessage
    // markers), this overlay uses a triplet format with explicit indices:
    //   [msg_index, field_id << 3 | opcode, argument] ... [checksum]
    // Each entry is exactly 3 varints. The argument is 0 when not needed.
    // Entries must be sorted by (msg_index, field_id).
    //
    // The parser processes bytecode_v2 and this overlay simultaneously:
    //  - any field not mentioned in the overlay is parsed as usual
    //  - any field in the overlay but *not* in the bytecode_v2 is added
    //    with its overlay value
    //  - any field in both the overlay and bytecode_v2 takes the value in the
    //    overlay, the bytecode_v2 value is ignored.
    //
    // Note: despite the name, this was broken in v54 (the overlay was not
    // passed through to the bytecode parser). Only works in v55+.
    optional bytes bytecode_overlay_v54 = 4;

    // String filter chain for Perfetto v54+. Rules in this chain either
    // overwrite rules in string_filter_chain (if the name matches) or are
    // appended (if the name doesn't match). This allows modifying existing
    // rules (e.g., changing policy) without duplicating the entire chain.
    // Rules without a name are always appended.
    // See /rfcs/0011-subset-string-filter-rules.md for design details.
    // Introduced in: Perfetto v54.
    optional StringFilterChain string_filter_chain_v54 = 5;
  }
  // 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;

  // When non-empty, ensures that for a each semaphore named `name at most
  // `max_other_session_count`` *other* sessions (whose value is taken of the
  // minimum of all values specified by this config or any already-running
  // session) can be be running.
  //
  // If a semaphore "acquisition" fails, EnableTracing will return an error
  // and the tracing session will not be started (or elgible to start in
  // the case of deferred sessions).
  //
  // This is easiest to explain with an example. Suppose the tracing service has
  // the following active tracing sessions:
  //   S1 = [{name=foo, max_other_session_count=2},
  //         {name=bar, max_other_session_count=0}]
  //   S2 = [{name=foo, max_other_session_count=1},
  //         {name=baz, max_other_session_count=1}]
  //
  // Then, for a new session, the following would be the expected behaviour of
  // EnableSession given the state of `session_semaphores`.
  //   Q: session_semaphores = []
  //   A: Allowed because it does not specify any semaphores. Will be allowed
  //      no matter the state of any other tracing session.
  //   Q: session_semaphores = [{name=baz, max_other_session_count=1}]
  //   A: Allowed because both S2 and this config specify
  //      max_other_session_count=1 for baz.
  //   Q: session_semaphores = [{name=foo, max_other_session_count=3}]
  //   A: Denied because S2 specified max_other_session_count=1 for foo and S1
  //      takes that slot.
  //   Q: session_semaphores = [{name=bar, max_other_session_count=0}]
  //   A: Denied because S1 takes the the slot specified by both S1 and
  //      this config.
  //
  // Introduced in 24Q3 (Android V).
  message SessionSemaphore {
    // The name of the semaphore. Acts as a unique identifier across all
    // tracing sessions (including the one being started).
    optional string name = 1;

    // The maximum number of *other* sesssions which specify the same semaphore
    // which can be active. The minimum of this value across all tracing
    // sessions and the value specified by the config is used when deciding
    // whether the tracing session can be started.
    optional uint64 max_other_session_count = 2;
  }
  repeated SessionSemaphore session_semaphores = 39;

  // Priority boost to be applied to the traced process, when the session is
  // running.
  optional PriorityBoostConfig priority_boost = 40;

  // When set to a value > 0, this tracing session will be started in
  // "exclusive mode". This has the following semantics:
  // - It can only be set by shell or root users.
  // - A new exclusive session will only be started if its priority is strictly
  //   higher than any other active tracing session.
  // - If a new exclusive session is started, all other existing tracing
  //   sessions (exclusive or not) are aborted.
  // - While an exclusive session is active, any new non-exclusive session (or
  //   any exclusive session with a lower or equal priority) will be rejected.
  //
  // Introduced in: perfetto v52.
  // Supported on: Android 25Q3+.
  optional uint32 exclusive_prio = 41;

  // Previously 'no_flush_before_write_into_file'. Now replaced by
  // 'write_flush_mode' to provide more granular control over flushing behavior
  // when streaming traces into a file. The original boolean was not enough to
  // represent the desired default behavior (flushing periodically but not
  // necessarily on every write).
  reserved 42;

  enum WriteFlushMode {
    // Same as WRITE_FLUSH_AUTO.
    WRITE_FLUSH_UNSPECIFIED = 0;

    // Default mode. The service automatically determines the flush frequency
    // to balance performance and data freshness:
    // 1) If file_write_period_ms <= 5s (kDefaultWriteIntoFilePeriodMs):
    //    Flushes are NOT issued on every write. Instead, a periodic flush is
    //    issued every 5s.
    // 2) If file_write_period_ms > 5s:
    //    A flush is issued before every periodic write into the file.
    WRITE_FLUSH_AUTO = 1;

    // The following modes are intended for advanced usage and not recommended
    // for general use.

    // Do not flush buffers before periodic writes into the file.
    // Use this mode if you want to minimize the performance impact of flushes
    // and can tolerate potentially missing the most recent data in the trace
    // file until the end of the session or an explicit flush.
    // When this mode is selected, |flush_period_ms| is respected.
    WRITE_FLUSH_DISABLED = 2;

    // Issue a flush before every periodic write into the file.
    // This ensures that each write into the file contains the most up-to-date
    // data from all data sources, but may have a higher performance overhead.
    WRITE_FLUSH_ENABLED = 3;
  }

  // Configures how the service should handle flushing data from producers
  // before periodically writing the trace into the output file.
  // Only applicable when |write_into_file| is true.
  //
  // By default, if |write_into_file| is set, the service periodically issues
  // a Flush() to all data sources before writing buffers into the file.
  // This ensures the file always contains the latest available data.
  //
  // Introduced in: perfetto v54.
  // Supported on: Android 26Q1+.
  optional WriteFlushMode write_flush_mode = 44;

  enum FFlushMode {
    // Default: same as FFLUSH_DISABLED.
    FFLUSH_UNSPECIFIED = 0;

    // Do not explicitly sync the file to storage after each write pass.
    FFLUSH_DISABLED = 1;

    // Explicitly sync the file to storage (via fdatasync) after each periodic
    // write pass. Increases data durability at the cost of higher disk I/O
    // overhead.
    FFLUSH_ENABLED = 2;
  }

  // Whether to sync the output file to storage after each periodic write pass.
  // Only applicable when |write_into_file| is true.
  //
  // By default, no fflush is invoked. FFLUSH_ENABLED must be set to explicitly
  // sync to storage on every write.
  //
  // Introduced in: perfetto v54.
  // Supported on: Android 26Q1+.
  optional FFlushMode fflush_post_write = 45;

  // When true, data sources in remote producers (machines connected via
  // traced_relay) will be matched by default. When false (the default), data
  // sources only match the host machine. In either case, an explicit
  // |DataSource.machine_name_filter| takes priority.
  //
  // NB: perfetto versions before v54 do not have this option and match across
  // machines by default. To be compatible across this version boundary, either
  // set this field to true, or set an explicit machine_name_filter on all data
  // sources.
  //
  // Introduced in: perfetto v54.
  optional bool trace_all_machines = 43;

  // Allow key, value pairs to save arbitrary data about trace.
  message Note {
    // Required.
    optional string key = 1;
    // Required.
    optional string value = 2;
  }
  repeated Note notes = 46;
}
