1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef INCLUDE_PERFETTO_TRACING_CORE_TRACING_SERVICE_H_
18 #define INCLUDE_PERFETTO_TRACING_CORE_TRACING_SERVICE_H_
19 
20 #include <stdint.h>
21 
22 #include <functional>
23 #include <memory>
24 #include <vector>
25 
26 #include "perfetto/base/export.h"
27 #include "perfetto/base/scoped_file.h"
28 #include "perfetto/tracing/core/basic_types.h"
29 #include "perfetto/tracing/core/shared_memory.h"
30 
31 namespace perfetto {
32 
33 namespace base {
34 class TaskRunner;
35 }  // namespace base
36 
37 class CommitDataRequest;
38 class Consumer;
39 class DataSourceDescriptor;
40 class Producer;
41 class SharedMemoryArbiter;
42 class TraceConfig;
43 class TraceWriter;
44 
45 // TODO: for the moment this assumes that all the calls happen on the same
46 // thread/sequence. Not sure this will be the case long term in Chrome.
47 
48 // The API for the Producer port of the Service.
49 // Subclassed by:
50 // 1. The tracing_service_impl.cc business logic when returning it in response
51 //    to the ConnectProducer() method.
52 // 2. The transport layer (e.g., src/ipc) when the producer and
53 //    the service don't talk locally but via some IPC mechanism.
54 class PERFETTO_EXPORT ProducerEndpoint {
55  public:
56   virtual ~ProducerEndpoint();
57 
58   // Called by the Producer to (un)register data sources. Data sources are
59   // identified by their name (i.e. DataSourceDescriptor.name)
60   virtual void RegisterDataSource(const DataSourceDescriptor&) = 0;
61   virtual void UnregisterDataSource(const std::string& name) = 0;
62 
63   // Associate the trace writer with the given |writer_id| with
64   // |target_buffer|. The service may use this information to retrieve and
65   // copy uncommitted chunks written by the trace writer into its associated
66   // buffer, e.g. when a producer process crashes or when a flush is
67   // necessary.
68   virtual void RegisterTraceWriter(uint32_t writer_id,
69                                    uint32_t target_buffer) = 0;
70 
71   // Remove the association of the trace writer previously created via
72   // RegisterTraceWriter.
73   virtual void UnregisterTraceWriter(uint32_t writer_id) = 0;
74 
75   // Called by the Producer to signal that some pages in the shared memory
76   // buffer (shared between Service and Producer) have changed.
77   // When the Producer and the Service are hosted in the same process and
78   // hence potentially live on the same task runner, This method must call
79   // TracingServiceImpl's CommitData synchronously, without any PostTask()s,
80   // if on the same thread. This is to avoid a deadlock where the Producer
81   // exhausts its SMB and stalls waiting for the service to catch up with
82   // reads, but the Service never gets to that because it lives on the same
83   // thread.
84   using CommitDataCallback = std::function<void()>;
85   virtual void CommitData(const CommitDataRequest&,
86                           CommitDataCallback callback = {}) = 0;
87 
88   virtual SharedMemory* shared_memory() const = 0;
89 
90   // Size of shared memory buffer pages. It's always a multiple of 4K.
91   // See shared_memory_abi.h
92   virtual size_t shared_buffer_page_size_kb() const = 0;
93 
94   // Creates a trace writer, which allows to create events, handling the
95   // underying shared memory buffer and signalling to the Service. This method
96   // is thread-safe but the returned object is not. A TraceWriter should be
97   // used only from a single thread, or the caller has to handle sequencing
98   // via a mutex or equivalent. This method can only be called if
99   // TracingService::ConnectProducer was called with |in_process=true|.
100   // Args:
101   // |target_buffer| is the target buffer ID where the data produced by the
102   // writer should be stored by the tracing service. This value is passed
103   // upon creation of the data source (StartDataSource()) in the
104   // DataSourceConfig.target_buffer().
105   virtual std::unique_ptr<TraceWriter> CreateTraceWriter(
106       BufferID target_buffer) = 0;
107 
108   // If TracingService::ConnectProducer is called with |in_process=true|,
109   // this returns the producer's SharedMemoryArbiter which can be used
110   // to create TraceWriters which is able to directly commit chunks
111   // without going through an IPC layer.
112   virtual SharedMemoryArbiter* GetInProcessShmemArbiter() = 0;
113 
114   // Called in response to a Producer::Flush(request_id) call after all data
115   // for the flush request has been committed.
116   virtual void NotifyFlushComplete(FlushRequestID) = 0;
117 
118   // Called in response to one or more Producer::StartDataSource(),
119   // if the data source registered setting the flag
120   // DataSourceDescriptor.will_notify_on_start.
121   virtual void NotifyDataSourceStarted(DataSourceInstanceID) = 0;
122 
123   // Called in response to one or more Producer::StopDataSource(),
124   // if the data source registered setting the flag
125   // DataSourceDescriptor.will_notify_on_stop.
126   virtual void NotifyDataSourceStopped(DataSourceInstanceID) = 0;
127 
128   // This informs the service to activate any of these triggers if any tracing
129   // session was waiting for them.
130   virtual void ActivateTriggers(const std::vector<std::string>&) = 0;
131 };  // class ProducerEndpoint.
132 
133 // The API for the Consumer port of the Service.
134 // Subclassed by:
135 // 1. The tracing_service_impl.cc business logic when returning it in response
136 // to
137 //    the ConnectConsumer() method.
138 // 2. The transport layer (e.g., src/ipc) when the consumer and
139 //    the service don't talk locally but via some IPC mechanism.
140 class ConsumerEndpoint {
141  public:
142   virtual ~ConsumerEndpoint();
143 
144   // Enables tracing with the given TraceConfig. The ScopedFile argument is
145   // used only when TraceConfig.write_into_file == true.
146   // If TraceConfig.deferred_start == true data sources are configured via
147   // SetupDataSource() but are not started until StartTracing() is called.
148   // This is to support pre-initialization and fast triggering of traces.
149   // The ScopedFile argument is used only when TraceConfig.write_into_file
150   // == true.
151   virtual void EnableTracing(const TraceConfig&,
152                              base::ScopedFile = base::ScopedFile()) = 0;
153 
154   // Update the trace config of an existing tracing session; only a subset
155   // of options can be changed mid-session. Currently the only
156   // supported functionality is expanding the list of producer_name_filters()
157   // (or removing the filter entirely) for existing data sources.
158   virtual void ChangeTraceConfig(const TraceConfig&) = 0;
159 
160   // Starts all data sources configured in the trace config. This is used only
161   // after calling EnableTracing() with TraceConfig.deferred_start=true.
162   // It's a no-op if called after a regular EnableTracing(), without setting
163   // deferred_start.
164   virtual void StartTracing() = 0;
165 
166   virtual void DisableTracing() = 0;
167 
168   // Requests all data sources to flush their data immediately and invokes the
169   // passed callback once all of them have acked the flush (in which case
170   // the callback argument |success| will be true) or |timeout_ms| are elapsed
171   // (in which case |success| will be false).
172   // If |timeout_ms| is 0 the TraceConfig's flush_timeout_ms is used, or,
173   // if that one is not set (or is set to 0), kDefaultFlushTimeoutMs (5s) is
174   // used.
175   using FlushCallback = std::function<void(bool /*success*/)>;
176   virtual void Flush(uint32_t timeout_ms, FlushCallback) = 0;
177 
178   // Tracing data will be delivered invoking Consumer::OnTraceData().
179   virtual void ReadBuffers() = 0;
180 
181   virtual void FreeBuffers() = 0;
182 
183   // Will call OnDetach().
184   virtual void Detach(const std::string& key) = 0;
185 
186   // Will call OnAttach().
187   virtual void Attach(const std::string& key) = 0;
188 
189   // Will call OnTraceStats().
190   virtual void GetTraceStats() = 0;
191 
192   enum ObservableEventType : uint32_t {
193     kNone = 0,
194     kDataSourceInstances = 1 << 0
195   };
196 
197   // Start or stop observing events of selected types. |enabled_event_types|
198   // specifies the types of events to observe in a bitmask (see
199   // ObservableEventType enum). To disable observing, pass
200   // ObservableEventType::kNone. Will call OnObservableEvents() repeatedly
201   // whenever an event of an enabled ObservableEventType occurs.
202   //
203   // TODO(eseckler): Extend this to support producers & data sources.
204   virtual void ObserveEvents(uint32_t enabled_event_types) = 0;
205 };  // class ConsumerEndpoint.
206 
207 // The public API of the tracing Service business logic.
208 //
209 // Exposed to:
210 // 1. The transport layer (e.g., src/unix_rpc/unix_service_host.cc),
211 //    which forwards commands received from a remote producer or consumer to
212 //    the actual service implementation.
213 // 2. Tests.
214 //
215 // Subclassed by:
216 //   The service business logic in src/core/tracing_service_impl.cc.
217 class PERFETTO_EXPORT TracingService {
218  public:
219   using ProducerEndpoint = perfetto::ProducerEndpoint;
220   using ConsumerEndpoint = perfetto::ConsumerEndpoint;
221 
222   enum class ProducerSMBScrapingMode {
223     // Use service's default setting for SMB scraping. Currently, the default
224     // mode is to disable SMB scraping, but this may change in the future.
225     kDefault,
226 
227     // Enable scraping of uncommitted chunks in producers' shared memory
228     // buffers.
229     kEnabled,
230 
231     // Disable scraping of uncommitted chunks in producers' shared memory
232     // buffers.
233     kDisabled
234   };
235 
236   // Implemented in src/core/tracing_service_impl.cc .
237   static std::unique_ptr<TracingService> CreateInstance(
238       std::unique_ptr<SharedMemory::Factory>,
239       base::TaskRunner*);
240 
241   virtual ~TracingService();
242 
243   // Connects a Producer instance and obtains a ProducerEndpoint, which is
244   // essentially a 1:1 channel between one Producer and the Service.
245   // The caller has to guarantee that the passed Producer will be alive as long
246   // as the returned ProducerEndpoint is alive.
247   // Both the passed Prodcer and the returned ProducerEndpint must live on the
248   // same task runner of the service, specifically:
249   // 1) The Service will call Producer::* methods on the Service's task runner.
250   // 2) The Producer should call ProducerEndpoint::* methods only on the
251   //    service's task runner, except for ProducerEndpoint::CreateTraceWriter(),
252   //    which can be called on any thread.
253   // To disconnect just destroy the returned ProducerEndpoint object. It is safe
254   // to destroy the Producer once the Producer::OnDisconnect() has been invoked.
255   // |uid| is the trusted user id of the producer process, used by the consumers
256   // for validating the origin of trace data.
257   // |shared_memory_size_hint_bytes| is an optional hint on the size of the
258   // shared memory buffer. The service can ignore the hint (e.g., if the hint
259   // is unreasonably large).
260   // |in_process| enables the ProducerEndpoint to manage its own shared memory
261   // and enables use of |ProducerEndpoint::CreateTraceWriter|.
262   // Can return null in the unlikely event that service has too many producers
263   // connected.
264   virtual std::unique_ptr<ProducerEndpoint> ConnectProducer(
265       Producer*,
266       uid_t uid,
267       const std::string& name,
268       size_t shared_memory_size_hint_bytes = 0,
269       bool in_process = false,
270       ProducerSMBScrapingMode smb_scraping_mode =
271           ProducerSMBScrapingMode::kDefault) = 0;
272 
273   // Connects a Consumer instance and obtains a ConsumerEndpoint, which is
274   // essentially a 1:1 channel between one Consumer and the Service.
275   // The caller has to guarantee that the passed Consumer will be alive as long
276   // as the returned ConsumerEndpoint is alive.
277   // To disconnect just destroy the returned ConsumerEndpoint object. It is safe
278   // to destroy the Consumer once the Consumer::OnDisconnect() has been invoked.
279   virtual std::unique_ptr<ConsumerEndpoint> ConnectConsumer(Consumer*,
280                                                             uid_t) = 0;
281 
282   // Enable/disable scraping of chunks in the shared memory buffer. If enabled,
283   // the service will copy uncommitted but non-empty chunks from the SMB when
284   // flushing (e.g. to handle unresponsive producers or producers unable to
285   // flush their active chunks), on producer disconnect (e.g. to recover data
286   // from crashed producers), and after disabling a tracing session (e.g. to
287   // gather data from producers that didn't stop their data sources in time).
288   //
289   // This feature is currently used by Chrome.
290   virtual void SetSMBScrapingEnabled(bool enabled) = 0;
291 };
292 
293 }  // namespace perfetto
294 
295 #endif  // INCLUDE_PERFETTO_TRACING_CORE_TRACING_SERVICE_H_
296