chromium/services/tracing/public/cpp/perfetto/fuchsia_perfetto_producer_connector.h

// Copyright 2022 The Chromium Authors
// 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_FUCHSIA_PERFETTO_PRODUCER_CONNECTOR_H_
#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_FUCHSIA_PERFETTO_PRODUCER_CONNECTOR_H_

#include <fidl/fuchsia.tracing.perfetto/cpp/fidl.h>
#include <perfetto/ext/ipc/client.h>
#include <perfetto/ext/tracing/core/shared_memory.h>

#include <optional>

#include "base/component_export.h"
#include "base/files/scoped_file.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/sequence_bound.h"
#include "base/threading/thread.h"
#include "base/tracing/perfetto_task_runner.h"

namespace tracing {

// Connects Perfetto sockets and shared memory channels on Fuchsia.
class COMPONENT_EXPORT(TRACING_CPP) FuchsiaPerfettoProducerConnector {
 public:
  explicit FuchsiaPerfettoProducerConnector(
      scoped_refptr<base::TaskRunner> perfetto_task_runner);
  ~FuchsiaPerfettoProducerConnector();

  // Returns a ConnArgs object with a socket connected to the system tracing
  // service if system tracing is provided by the platform.
  std::optional<perfetto::ipc::Client::ConnArgs> Connect();

  // Injects a ProducerConnector handle.
  void SetProducerServiceForTest(
      fidl::ClientEnd<fuchsia_tracing_perfetto::ProducerConnector> client_end);

 private:
  class BufferReceiverImpl;

  // Establishes a connection with the Perfetto system tracing service.
  // If successful, returns a file descriptor to the connected socket,
  // and a SharedMemoryTransport which will be used to propagate shared
  // memory buffers from the system tracing service to the client.
  // Returns an unset file descriptor and a null pointer if the system
  // tracing service could not be used.
  base::ScopedFD ConnectSocket();

  // Blocks until the tracing service provides a shared memory file descriptor.
  // Returns an invalid (-1) FD on timeout or error.
  int WaitForSharedMemoryFd();

  // Called when the BufferReceiver service has received a buffer from
  // the system tracing service.
  void OnSharedMemoryFdReceived(base::ScopedFD fd);

  fidl::ClientEnd<fuchsia_tracing_perfetto::ProducerConnector>
      producer_connector_client_end_for_test_;

  // Event used to synchronously wait until a file descriptor is received
  // from the system tracing service.
  base::WaitableEvent fd_received_event_{
      base::WaitableEvent::ResetPolicy::AUTOMATIC};

  // The file descriptor handled from |buffer_receiver_|.
  // Can be written on |buffer_receiver_thread_|, and read from any task runner.
  // Can only be read after |fd_received_event_| is signaled.
  base::ScopedFD received_fd_;

  // Implementation of the BufferReceiver FIDL service, used to receive
  // shared memory buffers from the system tracing service.
  // It runs on its own thread so that it will continue to operate even when
  // Perfetto is synchronously waiting for a buffer to arrive.
  // Deletion of |buffer_receiver_| will take place on |deletion_task_runner_|,
  // so as to prevent any use-after-free bugs if there are pending tasks which
  // reference BufferReceiver's callback.
  std::unique_ptr<base::Thread> buffer_receiver_thread_;
  base::SequenceBound<BufferReceiverImpl> buffer_receiver_;
  scoped_refptr<base::TaskRunner> deletion_task_runner_;
};

}  // namespace tracing

#endif  // SERVICES_TRACING_PUBLIC_CPP_PERFETTO_FUCHSIA_PERFETTO_PRODUCER_CONNECTOR_H_