Add initial Tracing Service implementation

The code still has lot of rough edges and TODOs, but
is in a good state to test integration with other system
components and cover CTS tests.

Bug: 70284518
Change-Id: Id6ac73426750cc4002d4e5bca65a66f4684c116b
diff --git a/src/tracing/core/service_impl.h b/src/tracing/core/service_impl.h
index 91db0fb..52b1277 100644
--- a/src/tracing/core/service_impl.h
+++ b/src/tracing/core/service_impl.h
@@ -22,9 +22,13 @@
 #include <memory>
 #include <set>
 
+#include "perfetto/base/utils.h"
 #include "perfetto/base/weak_ptr.h"
 #include "perfetto/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/data_source_descriptor.h"
 #include "perfetto/tracing/core/service.h"
+#include "perfetto/tracing/core/shared_memory_abi.h"
+#include "src/tracing/core/id_allocator.h"
 
 namespace perfetto {
 
@@ -71,6 +75,7 @@
     base::TaskRunner* const task_runner_;
     Producer* producer_;
     std::unique_ptr<SharedMemory> shared_memory_;
+    SharedMemoryABI shmem_abi_;
     DataSourceID last_data_source_id_ = 0;
   };
 
@@ -104,6 +109,13 @@
 
   // Called by ProducerEndpointImpl.
   void DisconnectProducer(ProducerID);
+  void RegisterDataSource(ProducerID,
+                          DataSourceID,
+                          const DataSourceDescriptor&);
+  void CopyProducerPageIntoLogBuffer(ProducerID,
+                                     BufferID,
+                                     const uint8_t*,
+                                     size_t);
 
   // Called by ConsumerEndpointImpl.
   void DisconnectConsumer(ConsumerEndpointImpl*);
@@ -125,14 +137,76 @@
   ProducerEndpointImpl* GetProducer(ProducerID) const;
 
  private:
+  struct RegisteredDataSource {
+    ProducerID producer_id;
+    DataSourceID data_source_id;
+    DataSourceDescriptor descriptor;
+  };
+
+  struct TraceBuffer {
+    // TODO(primiano): make this configurable.
+    static constexpr size_t kBufferPageSize = 4096;
+    explicit TraceBuffer(size_t size);
+    ~TraceBuffer();
+    TraceBuffer(TraceBuffer&&) noexcept;
+    TraceBuffer& operator=(TraceBuffer&&);
+
+    size_t num_pages() const { return size / kBufferPageSize; }
+
+    uint8_t* get_page(size_t page) {
+      PERFETTO_DCHECK(page < num_pages());
+      return reinterpret_cast<uint8_t*>(data.get()) + page * kBufferPageSize;
+    }
+
+    uint8_t* get_next_page() {
+      size_t cur = cur_page;
+      cur_page = cur_page == num_pages() - 1 ? 0 : cur_page + 1;
+      return get_page(cur);
+    }
+
+    size_t size;
+    size_t cur_page = 0;  // Write pointer in the ring buffer.
+    std::unique_ptr<void, base::FreeDeleter> data;
+
+    // TODO(primiano): The TraceBuffer is not shared and there is no reason to
+    // use the SharedMemoryABI. This is just a a temporary workaround to reuse
+    // the convenience of SharedMemoryABI for bookkeeping of the buffer when
+    // implementing ReadBuffers().
+    std::unique_ptr<SharedMemoryABI> abi;
+  };
+
+  // Holds the state of a tracing session. A tracing session is uniquely bound
+  // a specific Consumer. Each Consumer can own one or more sessions.
+  struct TracingSession {
+    // List of data source instances that have been enabled on the various
+    // producers for this tracing session.
+    std::multimap<ProducerID, DataSourceInstanceID> data_source_instances;
+
+    // The key of this map matches the |target_buffer| in the
+    // SharedMemoryABI::ChunkHeader.
+    std::map<BufferID, TraceBuffer> trace_buffers;
+  };
+
   ServiceImpl(const ServiceImpl&) = delete;
   ServiceImpl& operator=(const ServiceImpl&) = delete;
 
-  std::unique_ptr<SharedMemory::Factory> shm_factory_;
   base::TaskRunner* const task_runner_;
+  std::unique_ptr<SharedMemory::Factory> shm_factory_;
   ProducerID last_producer_id_ = 0;
+  DataSourceInstanceID last_data_source_instance_id_ = 0;
+
+  // Buffer IDs are global across all consumers (because a Producer can produce
+  // data for more than one trace session, hence more than one consumer).
+  IdAllocator buffer_ids_;
+
+  std::multimap<std::string /*name*/, RegisteredDataSource> data_sources_;
+
+  // TODO(primiano): There doesn't seem to be any good reason why |producers_|
+  // is a map indexed by ID and not just a set<ProducerEndpointImpl*>.
   std::map<ProducerID, ProducerEndpointImpl*> producers_;
+
   std::set<ConsumerEndpointImpl*> consumers_;
+  std::map<ConsumerEndpointImpl*, TracingSession> tracing_sessions_;
 };
 
 }  // namespace perfetto