text: // Copyright 2019 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #ifndef SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_PRODUCER_H_
  #define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_PRODUCER_H_
  
  #include <memory>
  
  #include "base/component_export.h"
  #include "base/memory/raw_ptr.h"
  #include "build/build_config.h"
  #include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
  #include "third_party/perfetto/include/perfetto/ext/tracing/core/basic_types.h"
  #include "third_party/perfetto/include/perfetto/ext/tracing/core/tracing_service.h"
  
  namespace perfetto {
  class SharedMemoryArbiter;
  }  // namespace perfetto
  
  namespace tracing {
  
  // This class represents the perfetto producer endpoint which is used for
  // producers to talk to the Perfetto service. It also provides methods to
  // interact with the shared memory buffer by binding and creating TraceWriters.
  //
  // In addition to the PerfettoProducers' pure virtual methods, subclasses must
  // implement the remaining methods of the ProducerEndpoint interface.
  class COMPONENT_EXPORT(TRACING_CPP) PerfettoProducer {
   public:
    explicit PerfettoProducer(base::tracing::PerfettoTaskRunner*);
  
    virtual ~PerfettoProducer();
  
    // Setup the shared memory buffer and data sources for startup tracing.
    // Returns false on failure. Can be called on any thread.
    bool SetupStartupTracing(const base::trace_event::TraceConfig&,
                             bool privacy_filtering_enabled);
  
    // Schedules the startup tracing timeout if active.
    void OnThreadPoolAvailable();
  
    // See SharedMemoryArbiter::CreateStartupTraceWriter.
    std::unique_ptr<perfetto::TraceWriter> CreateStartupTraceWriter(
        uint16_t target_buffer_reservation_id);
  
    // See SharedMemoryArbiter::BindStartupTargetBuffer. Should be called on the
    // producer's task runner.
    virtual void BindStartupTargetBuffer(
        uint16_t target_buffer_reservation_id,
        perfetto::BufferID startup_target_buffer);
  
    // See SharedMemoryArbiter::AbortStartupTracingForReservation. Should be
    // called on the producer's task runner.
    virtual void AbortStartupTracingForReservation(
        uint16_t target_buffer_reservation_id);
  
    // Used by the DataSource implementations to create TraceWriters
    // for writing their protobufs, and respond to flushes.
    //
    // Should only be called while a tracing session is active and a
    // SharedMemoryArbiter exists.
    //
    // Virtual for testing.
    virtual std::unique_ptr<perfetto::TraceWriter> CreateTraceWriter(
        perfetto::BufferID target_buffer,
        perfetto::BufferExhaustedPolicy =
            perfetto::BufferExhaustedPolicy::kDefault);
  
    // Returns the SharedMemoryArbiter if available.
    // TODO(eseckler): Once startup tracing v2 is available in Chrome, this could
    // become GetSharedMemoryArbiter() instead.
    virtual perfetto::SharedMemoryArbiter* MaybeSharedMemoryArbiter() = 0;
  
    // Informs the PerfettoProducer a new Data Source was added. This instance
    // will also be found in |data_sources| having just be inserted before this
    // method is called by PerfettoTracedProcess. This enables the
    // PerfettoProducer to perform initialization on new data sources.
    virtual void NewDataSourceAdded(
        const PerfettoTracedProcess::DataSourceBase* const data_source) = 0;
  
    // Returns true if this PerfettoProducer is currently tracing.
    virtual bool IsTracingActive() = 0;
  
    static void DeleteSoonForTesting(
        std::unique_ptr<PerfettoProducer> perfetto_producer);
  
    // In tests, PerfettoProducers may leak between tests, but their task sequence
    // may become invalid (e.g. TaskEnvironment is destroyed). This resets the
    // PerfettoProducer's sequence checker, so that it can later be rebound to a
    // new test's sequence. Note that this only resets the producer's sequence
    // checker - and there may be other sequence checkers elsewhere, e.g. in
    // PosixSystemProducer's socket (which would fail on disconnect if the system
    // producer's sequence is reset while it is connected).
    void ResetSequenceForTesting();
  
    void set_startup_tracing_timeout_for_testing(base::TimeDelta timeout) {
      startup_tracing_timeout_ = timeout;
    }
  
   protected:
    friend class MockProducerHost;
  
    // May be called on any thread.
    virtual bool SetupSharedMemoryForStartupTracing() = 0;
  
    // The PerfettoProducer subclass should call this once the startup tracing
    // session was taken over by the tracing service.
    // TODO(eseckler): Consider refactoring this into e.g. a delegate interface.
    void OnStartupTracingComplete();
  
    bool IsStartupTracingActive();
  
    // TODO(crbug.com/839071): Find a good compromise between performance and
    // data granularity (mainly relevant to running with small buffer sizes
    // when we use background tracing) on Android.
  #if defined(OS_ANDROID)
    static constexpr size_t kSMBPageSizeBytes = 4 * 1024;
  #else
    static constexpr size_t kSMBPageSizeBytes = 32 * 1024;
  #endif
  
    // TODO(crbug.com/839071): Figure out a good buffer size.
    static constexpr size_t kDefaultSMBSizeBytes = 4 * 1024 * 1024;
  
    // TODO(lri): replace this constant with its version in the client library,
    // when we move over.
    //
    // This value for SharedMemoryArbiter's batch_commits_duration_ms was
    // determined by load testing, using the script at
    // https://chromium-review.googlesource.com/c/chromium/src/+/1835498. The
    // effects of various delays on the overhead of tracing in Chrome
    // can be seen at https://screenshot.googleplex.com/KgsJshNCFKq. See commit
    // 2fc0474d9 and crbug.com/1029298 for more context.
    //
    // Note that since this value is non-zero, it could lead to loss of batched
    // data at the end of a tracing session. The producer should enable
    // asynchronous stopping of datasources and should flush the accumulated
    // commits while a datasource is being stopped.
    static constexpr uint32_t kShmArbiterBatchCommitDurationMs = 1000;
  
    base::tracing::PerfettoTaskRunner* task_runner();
  
    size_t GetPreferredSmbSizeBytes();
  
    SEQUENCE_CHECKER(sequence_checker_);
  
   private:
    void MaybeScheduleStartupTracingTimeout();
    void OnStartupTracingTimeout();
  
    // If a startup tracing session is not taken over by the service after this
    // delay, the startup session will be aborted and its data lost. This is to
    // catch situations where e.g. a subprocess is spawned with startup tracing
    // flags, but the tracing session got disabled in the service while it was
    // initializing (in which case, the tracing service will not tell the
    // subprocess to start tracing after it connects).
    base::TimeDelta startup_tracing_timeout_ = base::Seconds(60);
  
    const raw_ptr<base::tracing::PerfettoTaskRunner> task_runner_;
  
    std::atomic<bool> startup_tracing_active_{false};
  
    // NOTE: Weak pointers must be invalidated before all other member variables.
    base::WeakPtrFactory<PerfettoProducer> weak_ptr_factory_{this};
  };
  }  // namespace tracing
  #endif  // SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_PRODUCER_H_
  