blob: ce76ac7d6b7da332f70b2f9fcda78d1bb37aee85 [file] [log] [blame]
Primiano Tucci4f9b6d72017-12-05 20:59:16 +00001/*
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 SRC_TRACING_CORE_SERVICE_IMPL_H_
18#define SRC_TRACING_CORE_SERVICE_IMPL_H_
19
20#include <functional>
21#include <map>
22#include <memory>
Primiano Tucci42e2de12017-12-07 16:46:04 +000023#include <set>
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000024
Sami Kyostila32e0b542018-02-14 08:55:43 +000025#include "gtest/gtest_prod.h"
Primiano Tucci2ffd1a52018-03-27 01:01:30 +010026#include "perfetto/base/logging.h"
Primiano Tuccibbaa58c2017-12-20 13:48:20 +010027#include "perfetto/base/page_allocator.h"
Sami Kyostilafbccb3c2018-03-21 14:00:47 +000028#include "perfetto/base/time.h"
Primiano Tucci42e2de12017-12-07 16:46:04 +000029#include "perfetto/base/weak_ptr.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000030#include "perfetto/tracing/core/basic_types.h"
Primiano Tucciecf9e4a2018-03-14 14:51:58 +000031#include "perfetto/tracing/core/commit_data_request.h"
Primiano Tucci53589332017-12-19 11:31:13 +010032#include "perfetto/tracing/core/data_source_descriptor.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000033#include "perfetto/tracing/core/service.h"
Primiano Tucci53589332017-12-19 11:31:13 +010034#include "perfetto/tracing/core/shared_memory_abi.h"
Oystein Eftevaag1269b4a2018-01-10 16:29:38 -080035#include "perfetto/tracing/core/trace_config.h"
Primiano Tucci53589332017-12-19 11:31:13 +010036#include "src/tracing/core/id_allocator.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000037
38namespace perfetto {
39
40namespace base {
41class TaskRunner;
42} // namespace base
43
Primiano Tucci42e2de12017-12-07 16:46:04 +000044class Consumer;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000045class DataSourceConfig;
46class Producer;
47class SharedMemory;
Primiano Tucci2ffd1a52018-03-27 01:01:30 +010048class SharedMemoryArbiterImpl;
Primiano Tucciecf9e4a2018-03-14 14:51:58 +000049class TraceBuffez;
Primiano Tucci42e2de12017-12-07 16:46:04 +000050class TraceConfig;
Sami Kyostilafbccb3c2018-03-21 14:00:47 +000051class TracePacket;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000052
53// The tracing service business logic.
54class ServiceImpl : public Service {
55 public:
56 // The implementation behind the service endpoint exposed to each producer.
57 class ProducerEndpointImpl : public Service::ProducerEndpoint {
58 public:
59 ProducerEndpointImpl(ProducerID,
Sami Kyostila32e0b542018-02-14 08:55:43 +000060 uid_t uid,
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000061 ServiceImpl*,
62 base::TaskRunner*,
Isabelle Taylor69faa902018-03-21 15:42:03 +000063 Producer*);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000064 ~ProducerEndpointImpl() override;
65
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000066 // Service::ProducerEndpoint implementation.
67 void RegisterDataSource(const DataSourceDescriptor&,
68 RegisterDataSourceCallback) override;
69 void UnregisterDataSource(DataSourceID) override;
Primiano Tucci3e69ed92018-03-14 14:52:29 +000070 void CommitData(const CommitDataRequest&, CommitDataCallback) override;
Isabelle Taylor69faa902018-03-21 15:42:03 +000071 void SetSharedMemory(std::unique_ptr<SharedMemory>);
72
Primiano Tucciaf429f92017-12-19 01:51:50 +010073 std::unique_ptr<TraceWriter> CreateTraceWriter(BufferID) override;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000074 SharedMemory* shared_memory() const override;
Isabelle Taylor69faa902018-03-21 15:42:03 +000075 size_t shared_buffer_page_size_kb() const override;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000076
77 private:
Primiano Tucci20d441d2018-01-16 09:25:51 +000078 friend class ServiceImpl;
Sami Kyostila32e0b542018-02-14 08:55:43 +000079 FRIEND_TEST(ServiceImplTest, RegisterAndUnregister);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000080 ProducerEndpointImpl(const ProducerEndpointImpl&) = delete;
81 ProducerEndpointImpl& operator=(const ProducerEndpointImpl&) = delete;
82
83 ProducerID const id_;
Sami Kyostila32e0b542018-02-14 08:55:43 +000084 const uid_t uid_;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000085 ServiceImpl* const service_;
86 base::TaskRunner* const task_runner_;
87 Producer* producer_;
88 std::unique_ptr<SharedMemory> shared_memory_;
Isabelle Taylor69faa902018-03-21 15:42:03 +000089 size_t shared_buffer_page_size_kb_ = 0;
Primiano Tucci53589332017-12-19 11:31:13 +010090 SharedMemoryABI shmem_abi_;
Isabelle Taylor69faa902018-03-21 15:42:03 +000091 size_t shared_memory_size_hint_bytes_ = 0;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000092 DataSourceID last_data_source_id_ = 0;
Primiano Tucci2ffd1a52018-03-27 01:01:30 +010093
94 // This is used only in in-process configurations (mostly tests).
95 std::unique_ptr<SharedMemoryArbiterImpl> inproc_shmem_arbiter_;
96
Florian Mayercd08ec62018-01-31 17:49:25 +000097 PERFETTO_THREAD_CHECKER(thread_checker_)
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000098 };
99
Primiano Tucci42e2de12017-12-07 16:46:04 +0000100 // The implementation behind the service endpoint exposed to each consumer.
101 class ConsumerEndpointImpl : public Service::ConsumerEndpoint {
102 public:
103 ConsumerEndpointImpl(ServiceImpl*, base::TaskRunner*, Consumer*);
104 ~ConsumerEndpointImpl() override;
105
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100106 void NotifyOnTracingStop();
Primiano Tucci42e2de12017-12-07 16:46:04 +0000107 base::WeakPtr<ConsumerEndpointImpl> GetWeakPtr();
108
109 // Service::ConsumerEndpoint implementation.
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100110 void EnableTracing(const TraceConfig&, base::ScopedFile) override;
Primiano Tucci42e2de12017-12-07 16:46:04 +0000111 void DisableTracing() override;
112 void ReadBuffers() override;
113 void FreeBuffers() override;
114
115 private:
Primiano Tucci20d441d2018-01-16 09:25:51 +0000116 friend class ServiceImpl;
Primiano Tucci42e2de12017-12-07 16:46:04 +0000117 ConsumerEndpointImpl(const ConsumerEndpointImpl&) = delete;
118 ConsumerEndpointImpl& operator=(const ConsumerEndpointImpl&) = delete;
119
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100120 base::TaskRunner* const task_runner_;
Primiano Tucci42e2de12017-12-07 16:46:04 +0000121 ServiceImpl* const service_;
122 Consumer* const consumer_;
Primiano Tucci20d441d2018-01-16 09:25:51 +0000123 TracingSessionID tracing_session_id_ = 0;
Florian Mayercd08ec62018-01-31 17:49:25 +0000124
125 PERFETTO_THREAD_CHECKER(thread_checker_)
126
Primiano Tucci42e2de12017-12-07 16:46:04 +0000127 base::WeakPtrFactory<ConsumerEndpointImpl> weak_ptr_factory_;
128 };
129
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000130 explicit ServiceImpl(std::unique_ptr<SharedMemory::Factory>,
131 base::TaskRunner*);
132 ~ServiceImpl() override;
133
Primiano Tucci42e2de12017-12-07 16:46:04 +0000134 // Called by ProducerEndpointImpl.
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000135 void DisconnectProducer(ProducerID);
Primiano Tucci53589332017-12-19 11:31:13 +0100136 void RegisterDataSource(ProducerID,
137 DataSourceID,
138 const DataSourceDescriptor&);
Sami Kyostila06487a22018-02-27 13:48:38 +0000139 void UnregisterDataSource(ProducerID, DataSourceID);
Primiano Tucci53589332017-12-19 11:31:13 +0100140 void CopyProducerPageIntoLogBuffer(ProducerID,
Primiano Tucciecf9e4a2018-03-14 14:51:58 +0000141 uid_t,
142 WriterID,
143 ChunkID,
Primiano Tucci53589332017-12-19 11:31:13 +0100144 BufferID,
Primiano Tucciecf9e4a2018-03-14 14:51:58 +0000145 uint16_t num_fragments,
146 uint8_t chunk_flags,
147 const uint8_t* src,
148 size_t size);
149 void ApplyChunkPatches(ProducerID,
150 const std::vector<CommitDataRequest::ChunkToPatch>&);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000151
Primiano Tucci42e2de12017-12-07 16:46:04 +0000152 // Called by ConsumerEndpointImpl.
153 void DisconnectConsumer(ConsumerEndpointImpl*);
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100154 bool EnableTracing(ConsumerEndpointImpl*,
155 const TraceConfig&,
156 base::ScopedFile);
Primiano Tucci20d441d2018-01-16 09:25:51 +0000157 void DisableTracing(TracingSessionID);
158 void ReadBuffers(TracingSessionID, ConsumerEndpointImpl*);
159 void FreeBuffers(TracingSessionID);
Primiano Tucci42e2de12017-12-07 16:46:04 +0000160
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000161 // Service implementation.
162 std::unique_ptr<Service::ProducerEndpoint> ConnectProducer(
163 Producer*,
Sami Kyostila32e0b542018-02-14 08:55:43 +0000164 uid_t uid,
Isabelle Taylor69faa902018-03-21 15:42:03 +0000165 size_t shared_memory_size_hint_bytes = 0) override;
Primiano Tucci42e2de12017-12-07 16:46:04 +0000166
167 std::unique_ptr<Service::ConsumerEndpoint> ConnectConsumer(
168 Consumer*) override;
169
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000170 // Exposed mainly for testing.
171 size_t num_producers() const { return producers_.size(); }
172 ProducerEndpointImpl* GetProducer(ProducerID) const;
173
174 private:
Primiano Tucci081d46a2018-02-28 11:09:43 +0000175 FRIEND_TEST(ServiceImplTest, ProducerIDWrapping);
176
Primiano Tucci53589332017-12-19 11:31:13 +0100177 struct RegisteredDataSource {
178 ProducerID producer_id;
179 DataSourceID data_source_id;
180 DataSourceDescriptor descriptor;
181 };
182
Sami Kyostila06487a22018-02-27 13:48:38 +0000183 // Represents an active data source for a tracing session.
184 struct DataSourceInstance {
185 DataSourceInstanceID instance_id;
186 DataSourceID data_source_id;
187 };
188
Primiano Tucci53589332017-12-19 11:31:13 +0100189 // Holds the state of a tracing session. A tracing session is uniquely bound
190 // a specific Consumer. Each Consumer can own one or more sessions.
191 struct TracingSession {
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100192 TracingSession(ConsumerEndpointImpl*, const TraceConfig&);
Primiano Tucci20d441d2018-01-16 09:25:51 +0000193
194 size_t num_buffers() const { return buffers_index.size(); }
195
Isabelle Taylor69faa902018-03-21 15:42:03 +0000196 // Retrieves the page size from the trace config.
197 size_t GetDesiredPageSizeKb();
198
199 // Retrieves the SHM size from the trace config.
200 size_t GetDesiredShmSizeKb();
201
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100202 int next_write_period_ms() const {
203 PERFETTO_DCHECK(write_period_ms);
204 // TODO(primiano): this will drift. Synchronize % period so it aligns.
205 return write_period_ms;
206 }
207
208 // The consumer that started the session.
209 ConsumerEndpointImpl* const consumer;
210
Primiano Tucci20d441d2018-01-16 09:25:51 +0000211 // The original trace config provided by the Consumer when calling
212 // EnableTracing().
213 const TraceConfig config;
Oystein Eftevaag1269b4a2018-01-10 16:29:38 -0800214
Primiano Tucci53589332017-12-19 11:31:13 +0100215 // List of data source instances that have been enabled on the various
216 // producers for this tracing session.
Sami Kyostila06487a22018-02-27 13:48:38 +0000217 std::multimap<ProducerID, DataSourceInstance> data_source_instances;
Primiano Tucci53589332017-12-19 11:31:13 +0100218
Primiano Tucci20d441d2018-01-16 09:25:51 +0000219 // Maps a per-trace-session buffer index into the corresponding global
220 // BufferID (shared namespace amongst all consumers). This vector has as
221 // many entries as |config.buffers_size()|.
222 std::vector<BufferID> buffers_index;
Sami Kyostilafbccb3c2018-03-21 14:00:47 +0000223
224 // When the last clock snapshot was emitted into the output stream.
225 base::TimeMillis last_clock_snapshot = {};
Sami Kyostila200bd2e2018-03-26 12:24:10 +0100226
227 // Whether we mirrored the trace config back to the trace output yet.
228 bool did_emit_config = false;
Primiano Tucci2ffd1a52018-03-27 01:01:30 +0100229
230 bool tracing_enabled = false;
231
232 // This is set when the Consumer calls sets |write_into_file| == true in the
233 // TraceConfig. In this case this represents the file we should stream the
234 // trace packets into, rather than returning it to the consumer via
235 // OnTraceData().
236 base::ScopedFile write_into_file;
237 int write_period_ms = 0;
238 size_t max_file_size_bytes = 0;
239 size_t bytes_written_into_file = 0;
Primiano Tucci53589332017-12-19 11:31:13 +0100240 };
241
Primiano Tucci20d441d2018-01-16 09:25:51 +0000242 ServiceImpl(const ServiceImpl&) = delete;
243 ServiceImpl& operator=(const ServiceImpl&) = delete;
244
Sami Kyostila06487a22018-02-27 13:48:38 +0000245 void CreateDataSourceInstance(const TraceConfig::DataSource&,
246 const RegisteredDataSource&,
247 TracingSession*);
Oystein Eftevaag1269b4a2018-01-10 16:29:38 -0800248
Primiano Tucci081d46a2018-02-28 11:09:43 +0000249 // Returns the next available ProducerID that is not in |producers_|.
250 ProducerID GetNextProducerID();
251
Primiano Tucci20d441d2018-01-16 09:25:51 +0000252 // Returns a pointer to the |tracing_sessions_| entry or nullptr if the
253 // session doesn't exists.
254 TracingSession* GetTracingSession(TracingSessionID);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000255
Lalit Maganti485faff2018-03-06 11:51:35 +0000256 // Update the memory guard rail by using the latest information from the
257 // shared memory and trace buffers.
258 void UpdateMemoryGuardrail();
259
Sami Kyostilafbccb3c2018-03-21 14:00:47 +0000260 void MaybeSnapshotClocks(TracingSession*, std::vector<TracePacket>*);
Sami Kyostila200bd2e2018-03-26 12:24:10 +0100261 void MaybeEmitTraceConfig(TracingSession*, std::vector<TracePacket>*);
Sami Kyostilafbccb3c2018-03-21 14:00:47 +0000262
Primiano Tucciecf9e4a2018-03-14 14:51:58 +0000263 TraceBuffez* GetBufferByID(BufferID);
264
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000265 base::TaskRunner* const task_runner_;
Primiano Tucci53589332017-12-19 11:31:13 +0100266 std::unique_ptr<SharedMemory::Factory> shm_factory_;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000267 ProducerID last_producer_id_ = 0;
Primiano Tucci53589332017-12-19 11:31:13 +0100268 DataSourceInstanceID last_data_source_instance_id_ = 0;
Primiano Tucci20d441d2018-01-16 09:25:51 +0000269 TracingSessionID last_tracing_session_id_ = 0;
Isabelle Taylor69faa902018-03-21 15:42:03 +0000270 size_t shared_memory_size_hint_bytes_ = 0;
Primiano Tucci53589332017-12-19 11:31:13 +0100271
272 // Buffer IDs are global across all consumers (because a Producer can produce
273 // data for more than one trace session, hence more than one consumer).
Primiano Tucci20d441d2018-01-16 09:25:51 +0000274 IdAllocator<BufferID> buffer_ids_;
Primiano Tucci53589332017-12-19 11:31:13 +0100275
276 std::multimap<std::string /*name*/, RegisteredDataSource> data_sources_;
277
278 // TODO(primiano): There doesn't seem to be any good reason why |producers_|
279 // is a map indexed by ID and not just a set<ProducerEndpointImpl*>.
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000280 std::map<ProducerID, ProducerEndpointImpl*> producers_;
Primiano Tucci53589332017-12-19 11:31:13 +0100281
Primiano Tucci42e2de12017-12-07 16:46:04 +0000282 std::set<ConsumerEndpointImpl*> consumers_;
Primiano Tucci20d441d2018-01-16 09:25:51 +0000283 std::map<TracingSessionID, TracingSession> tracing_sessions_;
Primiano Tucciecf9e4a2018-03-14 14:51:58 +0000284 std::map<BufferID, std::unique_ptr<TraceBuffez>> buffers_;
Primiano Tucci20d441d2018-01-16 09:25:51 +0000285
Florian Mayer61c55482018-03-06 14:43:54 +0000286 bool lockdown_mode_ = false;
287
Florian Mayercd08ec62018-01-31 17:49:25 +0000288 PERFETTO_THREAD_CHECKER(thread_checker_)
289
Primiano Tucci20d441d2018-01-16 09:25:51 +0000290 base::WeakPtrFactory<ServiceImpl> weak_ptr_factory_; // Keep at the end.
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000291};
292
293} // namespace perfetto
294
295#endif // SRC_TRACING_CORE_SERVICE_IMPL_H_