Add support for long running traces

This CL adds the ability to pass a file descriptor to the
service when enabling tracing and periodically draining the
trace buffers into that file directly from the service.
This CL does not change the default behavior (which is: stream
the trace over IPC) but allows to change it when setting
|write_into_file|==true into the trace config.

More in details this CL:
- Adds new fields to the trace config to support passing the
  FD, as well as tuning the write period and max file size.
- Adds an explicit OnTracingStop() notification to the
  Consumer, as it can no longer rely on
  OnTraceData(has_more==false) to determine when tracing ended.
- Removes the OptimizeFor argument of TraceConfig, which ended
  up being never-used.
- Adds a SIGINT signal handler to the perfetto cmdline client,
  allowing to gracefully stop the trace and get back the results
  when hitting CTRL-c once.
- Stops using a temporary file when NOT using --dropbox, as the
  trace file will be valid even if not finalized.
- Add large traces support to trace_to_text by tokenizing the
  packets before passing them to the protobuf decoder (which would
  accept at most a 64M protobuf)

Matching SELinux CL: aosp/648831

Test: perfetto_unittests --gtest_filter=TracingIntegrationTest.*
Bug: 73625179
Change-Id: I28043bdbef6cac730f1797b6bc5b72ecf0acac79
diff --git a/src/tracing/core/service_impl.h b/src/tracing/core/service_impl.h
index ef01232..ce76ac7 100644
--- a/src/tracing/core/service_impl.h
+++ b/src/tracing/core/service_impl.h
@@ -23,6 +23,7 @@
 #include <set>
 
 #include "gtest/gtest_prod.h"
+#include "perfetto/base/logging.h"
 #include "perfetto/base/page_allocator.h"
 #include "perfetto/base/time.h"
 #include "perfetto/base/weak_ptr.h"
@@ -44,6 +45,7 @@
 class DataSourceConfig;
 class Producer;
 class SharedMemory;
+class SharedMemoryArbiterImpl;
 class TraceBuffez;
 class TraceConfig;
 class TracePacket;
@@ -88,6 +90,10 @@
     SharedMemoryABI shmem_abi_;
     size_t shared_memory_size_hint_bytes_ = 0;
     DataSourceID last_data_source_id_ = 0;
+
+    // This is used only in in-process configurations (mostly tests).
+    std::unique_ptr<SharedMemoryArbiterImpl> inproc_shmem_arbiter_;
+
     PERFETTO_THREAD_CHECKER(thread_checker_)
   };
 
@@ -97,10 +103,11 @@
     ConsumerEndpointImpl(ServiceImpl*, base::TaskRunner*, Consumer*);
     ~ConsumerEndpointImpl() override;
 
+    void NotifyOnTracingStop();
     base::WeakPtr<ConsumerEndpointImpl> GetWeakPtr();
 
     // Service::ConsumerEndpoint implementation.
-    void EnableTracing(const TraceConfig&) override;
+    void EnableTracing(const TraceConfig&, base::ScopedFile) override;
     void DisableTracing() override;
     void ReadBuffers() override;
     void FreeBuffers() override;
@@ -110,6 +117,7 @@
     ConsumerEndpointImpl(const ConsumerEndpointImpl&) = delete;
     ConsumerEndpointImpl& operator=(const ConsumerEndpointImpl&) = delete;
 
+    base::TaskRunner* const task_runner_;
     ServiceImpl* const service_;
     Consumer* const consumer_;
     TracingSessionID tracing_session_id_ = 0;
@@ -143,7 +151,9 @@
 
   // Called by ConsumerEndpointImpl.
   void DisconnectConsumer(ConsumerEndpointImpl*);
-  void EnableTracing(ConsumerEndpointImpl*, const TraceConfig&);
+  bool EnableTracing(ConsumerEndpointImpl*,
+                     const TraceConfig&,
+                     base::ScopedFile);
   void DisableTracing(TracingSessionID);
   void ReadBuffers(TracingSessionID, ConsumerEndpointImpl*);
   void FreeBuffers(TracingSessionID);
@@ -179,7 +189,7 @@
   // 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 {
-    explicit TracingSession(const TraceConfig&);
+    TracingSession(ConsumerEndpointImpl*, const TraceConfig&);
 
     size_t num_buffers() const { return buffers_index.size(); }
 
@@ -189,6 +199,15 @@
     // Retrieves the SHM size from the trace config.
     size_t GetDesiredShmSizeKb();
 
+    int next_write_period_ms() const {
+      PERFETTO_DCHECK(write_period_ms);
+      // TODO(primiano): this will drift. Synchronize % period so it aligns.
+      return write_period_ms;
+    }
+
+    // The consumer that started the session.
+    ConsumerEndpointImpl* const consumer;
+
     // The original trace config provided by the Consumer when calling
     // EnableTracing().
     const TraceConfig config;
@@ -207,6 +226,17 @@
 
     // Whether we mirrored the trace config back to the trace output yet.
     bool did_emit_config = false;
+
+    bool tracing_enabled = false;
+
+    // This is set when the Consumer calls sets |write_into_file| == true in the
+    // TraceConfig. In this case this represents the file we should stream the
+    // trace packets into, rather than returning it to the consumer via
+    // OnTraceData().
+    base::ScopedFile write_into_file;
+    int write_period_ms = 0;
+    size_t max_file_size_bytes = 0;
+    size_t bytes_written_into_file = 0;
   };
 
   ServiceImpl(const ServiceImpl&) = delete;