1 /*
2 * Copyright (C) 2018 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 #include "src/traced/probes/probes_producer.h"
18
19 #include <stdio.h>
20 #include <sys/stat.h>
21
22 #include <algorithm>
23 #include <queue>
24 #include <string>
25
26 #include "perfetto/base/logging.h"
27 #include "perfetto/ext/base/utils.h"
28 #include "perfetto/ext/base/watchdog.h"
29 #include "perfetto/ext/base/weak_ptr.h"
30 #include "perfetto/ext/traced/traced.h"
31 #include "perfetto/ext/tracing/core/trace_packet.h"
32 #include "perfetto/ext/tracing/ipc/producer_ipc_client.h"
33 #include "perfetto/tracing/core/data_source_config.h"
34 #include "perfetto/tracing/core/data_source_descriptor.h"
35 #include "perfetto/tracing/core/trace_config.h"
36 #include "src/traced/probes/android_log/android_log_data_source.h"
37 #include "src/traced/probes/common/cpu_freq_info.h"
38 #include "src/traced/probes/filesystem/inode_file_data_source.h"
39 #include "src/traced/probes/ftrace/ftrace_data_source.h"
40 #include "src/traced/probes/initial_display_state/initial_display_state_data_source.h"
41 #include "src/traced/probes/metatrace/metatrace_data_source.h"
42 #include "src/traced/probes/packages_list/packages_list_data_source.h"
43 #include "src/traced/probes/power/android_power_data_source.h"
44 #include "src/traced/probes/probes_data_source.h"
45 #include "src/traced/probes/ps/process_stats_data_source.h"
46 #include "src/traced/probes/sys_stats/sys_stats_data_source.h"
47 #include "src/traced/probes/system_info/system_info_data_source.h"
48
49 #include "protos/perfetto/config/ftrace/ftrace_config.gen.h"
50 #include "protos/perfetto/trace/filesystem/inode_file_map.pbzero.h"
51 #include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
52 #include "protos/perfetto/trace/ftrace/ftrace_stats.pbzero.h"
53 #include "protos/perfetto/trace/trace_packet.pbzero.h"
54
55 namespace perfetto {
56 namespace {
57
58 constexpr uint32_t kInitialConnectionBackoffMs = 100;
59 constexpr uint32_t kMaxConnectionBackoffMs = 30 * 1000;
60
61 // Should be larger than FtraceController::kControllerFlushTimeoutMs.
62 constexpr uint32_t kFlushTimeoutMs = 1000;
63
64 constexpr size_t kTracingSharedMemSizeHintBytes = 1024 * 1024;
65 constexpr size_t kTracingSharedMemPageSizeHintBytes = 32 * 1024;
66
67 ProbesDataSource::Descriptor const* const kAllDataSources[]{
68 &FtraceDataSource::descriptor, //
69 &ProcessStatsDataSource::descriptor, //
70 &InodeFileDataSource::descriptor, //
71 &SysStatsDataSource::descriptor, //
72 &AndroidPowerDataSource::descriptor, //
73 &AndroidLogDataSource::descriptor, //
74 &PackagesListDataSource::descriptor, //
75 &MetatraceDataSource::descriptor, //
76 &SystemInfoDataSource::descriptor, //
77 &InitialDisplayStateDataSource::descriptor, //
78 };
79 } // namespace
80
81 // State transition diagram:
82 // +----------------------------+
83 // v +
84 // NotStarted -> NotConnected -> Connecting -> Connected
85 // ^ +
86 // +--------------+
87 //
88
ProbesProducer()89 ProbesProducer::ProbesProducer() : weak_factory_(this) {}
~ProbesProducer()90 ProbesProducer::~ProbesProducer() {
91 // The ftrace data sources must be deleted before the ftrace controller.
92 data_sources_.clear();
93 ftrace_.reset();
94 }
95
OnConnect()96 void ProbesProducer::OnConnect() {
97 PERFETTO_DCHECK(state_ == kConnecting);
98 state_ = kConnected;
99 ResetConnectionBackoff();
100 PERFETTO_LOG("Connected to the service");
101
102 // Register all the data sources.
103 for (const FtraceDataSource::Descriptor* desc : kAllDataSources) {
104 DataSourceDescriptor proto_desc;
105 proto_desc.set_name(desc->name);
106 proto_desc.set_will_notify_on_start(true);
107 proto_desc.set_will_notify_on_stop(true);
108 using Flags = ProbesDataSource::Descriptor::Flags;
109 if (desc->flags & Flags::kHandlesIncrementalState)
110 proto_desc.set_handles_incremental_state_clear(true);
111 endpoint_->RegisterDataSource(proto_desc);
112 }
113 }
114
OnDisconnect()115 void ProbesProducer::OnDisconnect() {
116 PERFETTO_DCHECK(state_ == kConnected || state_ == kConnecting);
117 PERFETTO_LOG("Disconnected from tracing service");
118 if (state_ == kConnected)
119 return task_runner_->PostTask([this] { this->Restart(); });
120
121 state_ = kNotConnected;
122 IncreaseConnectionBackoff();
123 task_runner_->PostDelayedTask([this] { this->Connect(); },
124 connection_backoff_ms_);
125 }
126
Restart()127 void ProbesProducer::Restart() {
128 // We lost the connection with the tracing service. At this point we need
129 // to reset all the data sources. Trying to handle that manually is going to
130 // be error prone. What we do here is simply destroying the instance and
131 // recreating it again.
132
133 base::TaskRunner* task_runner = task_runner_;
134 const char* socket_name = socket_name_;
135
136 // Invoke destructor and then the constructor again.
137 this->~ProbesProducer();
138 new (this) ProbesProducer();
139
140 ConnectWithRetries(socket_name, task_runner);
141 }
142
SetupDataSource(DataSourceInstanceID instance_id,const DataSourceConfig & config)143 void ProbesProducer::SetupDataSource(DataSourceInstanceID instance_id,
144 const DataSourceConfig& config) {
145 PERFETTO_DLOG("SetupDataSource(id=%" PRIu64 ", name=%s)", instance_id,
146 config.name().c_str());
147 PERFETTO_DCHECK(data_sources_.count(instance_id) == 0);
148 TracingSessionID session_id = config.tracing_session_id();
149 PERFETTO_CHECK(session_id > 0);
150
151 std::unique_ptr<ProbesDataSource> data_source;
152 if (config.name() == FtraceDataSource::descriptor.name) {
153 data_source = CreateFtraceDataSource(session_id, config);
154 } else if (config.name() == InodeFileDataSource::descriptor.name) {
155 data_source = CreateInodeFileDataSource(session_id, config);
156 } else if (config.name() == ProcessStatsDataSource::descriptor.name) {
157 data_source = CreateProcessStatsDataSource(session_id, config);
158 } else if (config.name() == SysStatsDataSource::descriptor.name) {
159 data_source = CreateSysStatsDataSource(session_id, config);
160 } else if (config.name() == AndroidPowerDataSource::descriptor.name) {
161 data_source = CreateAndroidPowerDataSource(session_id, config);
162 } else if (config.name() == AndroidLogDataSource::descriptor.name) {
163 data_source = CreateAndroidLogDataSource(session_id, config);
164 } else if (config.name() == PackagesListDataSource::descriptor.name) {
165 data_source = CreatePackagesListDataSource(session_id, config);
166 } else if (config.name() == MetatraceDataSource::descriptor.name) {
167 data_source = CreateMetatraceDataSource(session_id, config);
168 } else if (config.name() == SystemInfoDataSource::descriptor.name) {
169 data_source = CreateSystemInfoDataSource(session_id, config);
170 } else if (config.name() == InitialDisplayStateDataSource::descriptor.name) {
171 data_source = CreateInitialDisplayStateDataSource(session_id, config);
172 }
173
174 if (!data_source) {
175 PERFETTO_ELOG("Failed to create data source '%s'", config.name().c_str());
176 return;
177 }
178
179 session_data_sources_.emplace(session_id, data_source.get());
180 data_sources_[instance_id] = std::move(data_source);
181 }
182
StartDataSource(DataSourceInstanceID instance_id,const DataSourceConfig & config)183 void ProbesProducer::StartDataSource(DataSourceInstanceID instance_id,
184 const DataSourceConfig& config) {
185 PERFETTO_DLOG("StartDataSource(id=%" PRIu64 ", name=%s)", instance_id,
186 config.name().c_str());
187 auto it = data_sources_.find(instance_id);
188 if (it == data_sources_.end()) {
189 // Can happen if SetupDataSource() failed (e.g. ftrace was busy).
190 PERFETTO_ELOG("Data source id=%" PRIu64 " not found", instance_id);
191 return;
192 }
193 ProbesDataSource* data_source = it->second.get();
194 if (data_source->started)
195 return;
196 if (config.trace_duration_ms() != 0) {
197 uint32_t timeout = 5000 + 2 * config.trace_duration_ms();
198 watchdogs_.emplace(
199 instance_id, base::Watchdog::GetInstance()->CreateFatalTimer(timeout));
200 }
201 data_source->started = true;
202 data_source->Start();
203 endpoint_->NotifyDataSourceStarted(instance_id);
204 }
205
CreateFtraceDataSource(TracingSessionID session_id,const DataSourceConfig & config)206 std::unique_ptr<ProbesDataSource> ProbesProducer::CreateFtraceDataSource(
207 TracingSessionID session_id,
208 const DataSourceConfig& config) {
209 // Don't retry if FtraceController::Create() failed once.
210 // This can legitimately happen on user builds where we cannot access the
211 // debug paths, e.g., because of SELinux rules.
212 if (ftrace_creation_failed_)
213 return nullptr;
214
215 // Lazily create on the first instance.
216 if (!ftrace_) {
217 ftrace_ = FtraceController::Create(task_runner_, this);
218
219 if (!ftrace_) {
220 PERFETTO_ELOG("Failed to create FtraceController");
221 ftrace_creation_failed_ = true;
222 return nullptr;
223 }
224
225 ftrace_->DisableAllEvents();
226 ftrace_->ClearTrace();
227 }
228
229 PERFETTO_LOG("Ftrace setup (target_buf=%" PRIu32 ")", config.target_buffer());
230 const BufferID buffer_id = static_cast<BufferID>(config.target_buffer());
231 FtraceConfig ftrace_config;
232 ftrace_config.ParseFromString(config.ftrace_config_raw());
233 std::unique_ptr<FtraceDataSource> data_source(new FtraceDataSource(
234 ftrace_->GetWeakPtr(), session_id, std::move(ftrace_config),
235 endpoint_->CreateTraceWriter(buffer_id)));
236 if (!ftrace_->AddDataSource(data_source.get())) {
237 PERFETTO_ELOG("Failed to setup ftrace");
238 return nullptr;
239 }
240 return std::unique_ptr<ProbesDataSource>(std::move(data_source));
241 }
242
CreateInodeFileDataSource(TracingSessionID session_id,DataSourceConfig source_config)243 std::unique_ptr<ProbesDataSource> ProbesProducer::CreateInodeFileDataSource(
244 TracingSessionID session_id,
245 DataSourceConfig source_config) {
246 PERFETTO_LOG("Inode file map setup (target_buf=%" PRIu32 ")",
247 source_config.target_buffer());
248 auto buffer_id = static_cast<BufferID>(source_config.target_buffer());
249 if (system_inodes_.empty())
250 CreateStaticDeviceToInodeMap("/system", &system_inodes_);
251 return std::unique_ptr<InodeFileDataSource>(new InodeFileDataSource(
252 std::move(source_config), task_runner_, session_id, &system_inodes_,
253 &cache_, endpoint_->CreateTraceWriter(buffer_id)));
254 }
255
CreateProcessStatsDataSource(TracingSessionID session_id,const DataSourceConfig & config)256 std::unique_ptr<ProbesDataSource> ProbesProducer::CreateProcessStatsDataSource(
257 TracingSessionID session_id,
258 const DataSourceConfig& config) {
259 auto buffer_id = static_cast<BufferID>(config.target_buffer());
260 return std::unique_ptr<ProcessStatsDataSource>(new ProcessStatsDataSource(
261 task_runner_, session_id, endpoint_->CreateTraceWriter(buffer_id), config,
262 std::unique_ptr<CpuFreqInfo>(new CpuFreqInfo())));
263 }
264
CreateAndroidPowerDataSource(TracingSessionID session_id,const DataSourceConfig & config)265 std::unique_ptr<ProbesDataSource> ProbesProducer::CreateAndroidPowerDataSource(
266 TracingSessionID session_id,
267 const DataSourceConfig& config) {
268 auto buffer_id = static_cast<BufferID>(config.target_buffer());
269 return std::unique_ptr<ProbesDataSource>(
270 new AndroidPowerDataSource(config, task_runner_, session_id,
271 endpoint_->CreateTraceWriter(buffer_id)));
272 }
273
CreateAndroidLogDataSource(TracingSessionID session_id,const DataSourceConfig & config)274 std::unique_ptr<ProbesDataSource> ProbesProducer::CreateAndroidLogDataSource(
275 TracingSessionID session_id,
276 const DataSourceConfig& config) {
277 auto buffer_id = static_cast<BufferID>(config.target_buffer());
278 return std::unique_ptr<ProbesDataSource>(
279 new AndroidLogDataSource(config, task_runner_, session_id,
280 endpoint_->CreateTraceWriter(buffer_id)));
281 }
282
CreatePackagesListDataSource(TracingSessionID session_id,const DataSourceConfig & config)283 std::unique_ptr<ProbesDataSource> ProbesProducer::CreatePackagesListDataSource(
284 TracingSessionID session_id,
285 const DataSourceConfig& config) {
286 auto buffer_id = static_cast<BufferID>(config.target_buffer());
287 return std::unique_ptr<ProbesDataSource>(new PackagesListDataSource(
288 config, session_id, endpoint_->CreateTraceWriter(buffer_id)));
289 }
290
CreateSysStatsDataSource(TracingSessionID session_id,const DataSourceConfig & config)291 std::unique_ptr<ProbesDataSource> ProbesProducer::CreateSysStatsDataSource(
292 TracingSessionID session_id,
293 const DataSourceConfig& config) {
294 auto buffer_id = static_cast<BufferID>(config.target_buffer());
295 return std::unique_ptr<SysStatsDataSource>(
296 new SysStatsDataSource(task_runner_, session_id,
297 endpoint_->CreateTraceWriter(buffer_id), config));
298 }
299
CreateMetatraceDataSource(TracingSessionID session_id,const DataSourceConfig & config)300 std::unique_ptr<ProbesDataSource> ProbesProducer::CreateMetatraceDataSource(
301 TracingSessionID session_id,
302 const DataSourceConfig& config) {
303 auto buffer_id = static_cast<BufferID>(config.target_buffer());
304 return std::unique_ptr<ProbesDataSource>(new MetatraceDataSource(
305 task_runner_, session_id, endpoint_->CreateTraceWriter(buffer_id)));
306 }
307
CreateSystemInfoDataSource(TracingSessionID session_id,const DataSourceConfig & config)308 std::unique_ptr<ProbesDataSource> ProbesProducer::CreateSystemInfoDataSource(
309 TracingSessionID session_id,
310 const DataSourceConfig& config) {
311 auto buffer_id = static_cast<BufferID>(config.target_buffer());
312 return std::unique_ptr<ProbesDataSource>(new SystemInfoDataSource(
313 session_id, endpoint_->CreateTraceWriter(buffer_id),
314 std::unique_ptr<CpuFreqInfo>(new CpuFreqInfo())));
315 }
316
317 std::unique_ptr<ProbesDataSource>
CreateInitialDisplayStateDataSource(TracingSessionID session_id,const DataSourceConfig & config)318 ProbesProducer::CreateInitialDisplayStateDataSource(
319 TracingSessionID session_id,
320 const DataSourceConfig& config) {
321 auto buffer_id = static_cast<BufferID>(config.target_buffer());
322 return std::unique_ptr<ProbesDataSource>(new InitialDisplayStateDataSource(
323 task_runner_, config, session_id,
324 endpoint_->CreateTraceWriter(buffer_id)));
325 }
326
StopDataSource(DataSourceInstanceID id)327 void ProbesProducer::StopDataSource(DataSourceInstanceID id) {
328 PERFETTO_LOG("Producer stop (id=%" PRIu64 ")", id);
329 auto it = data_sources_.find(id);
330 if (it == data_sources_.end()) {
331 // Can happen if SetupDataSource() failed (e.g. ftrace was busy).
332 PERFETTO_ELOG("Cannot stop data source id=%" PRIu64 ", not found", id);
333 return;
334 }
335 ProbesDataSource* data_source = it->second.get();
336
337 // MetatraceDataSource special case: re-flush and ack the stop (to record the
338 // flushes of other data sources).
339 if (data_source->descriptor == &MetatraceDataSource::descriptor)
340 data_source->Flush(FlushRequestID{0}, [] {});
341
342 endpoint_->NotifyDataSourceStopped(id);
343
344 TracingSessionID session_id = data_source->tracing_session_id;
345 auto range = session_data_sources_.equal_range(session_id);
346 for (auto kv = range.first; kv != range.second; kv++) {
347 if (kv->second != data_source)
348 continue;
349 session_data_sources_.erase(kv);
350 break;
351 }
352 data_sources_.erase(it);
353 watchdogs_.erase(id);
354 }
355
OnTracingSetup()356 void ProbesProducer::OnTracingSetup() {
357 // shared_memory() can be null in test environments when running in-process.
358 if (endpoint_->shared_memory()) {
359 base::Watchdog::GetInstance()->SetMemoryLimit(
360 endpoint_->shared_memory()->size() + base::kWatchdogDefaultMemorySlack,
361 base::kWatchdogDefaultMemoryWindow);
362 }
363 }
364
Flush(FlushRequestID flush_request_id,const DataSourceInstanceID * data_source_ids,size_t num_data_sources)365 void ProbesProducer::Flush(FlushRequestID flush_request_id,
366 const DataSourceInstanceID* data_source_ids,
367 size_t num_data_sources) {
368 PERFETTO_DCHECK(flush_request_id);
369 auto weak_this = weak_factory_.GetWeakPtr();
370
371 // Issue a Flush() to all started data sources.
372 bool flush_queued = false;
373 for (size_t i = 0; i < num_data_sources; i++) {
374 DataSourceInstanceID ds_id = data_source_ids[i];
375 auto it = data_sources_.find(ds_id);
376 if (it == data_sources_.end() || !it->second->started)
377 continue;
378 pending_flushes_.emplace(flush_request_id, ds_id);
379 flush_queued = true;
380 auto flush_callback = [weak_this, flush_request_id, ds_id] {
381 if (weak_this)
382 weak_this->OnDataSourceFlushComplete(flush_request_id, ds_id);
383 };
384 it->second->Flush(flush_request_id, flush_callback);
385 }
386
387 // If there is nothing to flush, ack immediately.
388 if (!flush_queued) {
389 endpoint_->NotifyFlushComplete(flush_request_id);
390 return;
391 }
392
393 // Otherwise, post the timeout task.
394 task_runner_->PostDelayedTask(
395 [weak_this, flush_request_id] {
396 if (weak_this)
397 weak_this->OnFlushTimeout(flush_request_id);
398 },
399 kFlushTimeoutMs);
400 }
401
OnDataSourceFlushComplete(FlushRequestID flush_request_id,DataSourceInstanceID ds_id)402 void ProbesProducer::OnDataSourceFlushComplete(FlushRequestID flush_request_id,
403 DataSourceInstanceID ds_id) {
404 PERFETTO_DLOG("Flush %" PRIu64 " acked by data source %" PRIu64,
405 flush_request_id, ds_id);
406 auto range = pending_flushes_.equal_range(flush_request_id);
407 for (auto it = range.first; it != range.second; it++) {
408 if (it->second == ds_id) {
409 pending_flushes_.erase(it);
410 break;
411 }
412 }
413
414 if (pending_flushes_.count(flush_request_id))
415 return; // Still waiting for other data sources to ack.
416
417 PERFETTO_DLOG("All data sources acked to flush %" PRIu64, flush_request_id);
418 endpoint_->NotifyFlushComplete(flush_request_id);
419 }
420
OnFlushTimeout(FlushRequestID flush_request_id)421 void ProbesProducer::OnFlushTimeout(FlushRequestID flush_request_id) {
422 if (pending_flushes_.count(flush_request_id) == 0)
423 return; // All acked.
424 PERFETTO_ELOG("Flush(%" PRIu64 ") timed out", flush_request_id);
425 pending_flushes_.erase(flush_request_id);
426 endpoint_->NotifyFlushComplete(flush_request_id);
427 }
428
ClearIncrementalState(const DataSourceInstanceID * data_source_ids,size_t num_data_sources)429 void ProbesProducer::ClearIncrementalState(
430 const DataSourceInstanceID* data_source_ids,
431 size_t num_data_sources) {
432 for (size_t i = 0; i < num_data_sources; i++) {
433 DataSourceInstanceID ds_id = data_source_ids[i];
434 auto it = data_sources_.find(ds_id);
435 if (it == data_sources_.end() || !it->second->started)
436 continue;
437
438 it->second->ClearIncrementalState();
439 }
440 }
441
442 // This function is called by the FtraceController in batches, whenever it has
443 // read one or more pages from one or more cpus and written that into the
444 // userspace tracing buffer. If more than one ftrace data sources are active,
445 // this call typically happens after writing for all session has been handled.
OnFtraceDataWrittenIntoDataSourceBuffers()446 void ProbesProducer::OnFtraceDataWrittenIntoDataSourceBuffers() {
447 TracingSessionID last_session_id = 0;
448 FtraceMetadata* metadata = nullptr;
449 InodeFileDataSource* inode_data_source = nullptr;
450 ProcessStatsDataSource* ps_data_source = nullptr;
451
452 // unordered_multimap guarantees that entries with the same key are contiguous
453 // in the iteration.
454 for (auto it = session_data_sources_.begin(); /* check below*/; it++) {
455 // If this is the last iteration or the session id has changed,
456 // dispatch the metadata update to the linked data sources, if any.
457 if (it == session_data_sources_.end() || it->first != last_session_id) {
458 bool has_inodes = metadata && !metadata->inode_and_device.empty();
459 bool has_pids = metadata && !metadata->pids.empty();
460 bool has_rename_pids = metadata && !metadata->rename_pids.empty();
461 if (has_inodes && inode_data_source)
462 inode_data_source->OnInodes(metadata->inode_and_device);
463 // Ordering the rename pids before the seen pids is important so that any
464 // renamed processes get scraped in the OnPids call.
465 if (has_rename_pids && ps_data_source)
466 ps_data_source->OnRenamePids(metadata->rename_pids);
467 if (has_pids && ps_data_source)
468 ps_data_source->OnPids(metadata->pids);
469 if (metadata)
470 metadata->Clear();
471 metadata = nullptr;
472 inode_data_source = nullptr;
473 ps_data_source = nullptr;
474 if (it == session_data_sources_.end())
475 break;
476 last_session_id = it->first;
477 }
478 ProbesDataSource* ds = it->second;
479 if (!ds->started)
480 continue;
481
482 if (ds->descriptor == &FtraceDataSource::descriptor) {
483 metadata = static_cast<FtraceDataSource*>(ds)->mutable_metadata();
484 } else if (ds->descriptor == &InodeFileDataSource::descriptor) {
485 inode_data_source = static_cast<InodeFileDataSource*>(ds);
486 } else if (ds->descriptor == &ProcessStatsDataSource::descriptor) {
487 // A trace session might have declared more than one ps data source.
488 // In those cases we often use one for a full dump on startup (
489 // targeting a dedicated buffer) and another one for on-demand dumps
490 // targeting the main buffer.
491 // Only use the one that has on-demand dumps enabled, if any.
492 auto ps = static_cast<ProcessStatsDataSource*>(ds);
493 if (ps->on_demand_dumps_enabled())
494 ps_data_source = ps;
495 }
496 } // for (session_data_sources_)
497 }
498
ConnectWithRetries(const char * socket_name,base::TaskRunner * task_runner)499 void ProbesProducer::ConnectWithRetries(const char* socket_name,
500 base::TaskRunner* task_runner) {
501 PERFETTO_DCHECK(state_ == kNotStarted);
502 state_ = kNotConnected;
503
504 ResetConnectionBackoff();
505 socket_name_ = socket_name;
506 task_runner_ = task_runner;
507 Connect();
508 }
509
Connect()510 void ProbesProducer::Connect() {
511 PERFETTO_DCHECK(state_ == kNotConnected);
512 state_ = kConnecting;
513 endpoint_ = ProducerIPCClient::Connect(
514 socket_name_, this, "perfetto.traced_probes", task_runner_,
515 TracingService::ProducerSMBScrapingMode::kDisabled,
516 kTracingSharedMemSizeHintBytes, kTracingSharedMemPageSizeHintBytes);
517 }
518
IncreaseConnectionBackoff()519 void ProbesProducer::IncreaseConnectionBackoff() {
520 connection_backoff_ms_ *= 2;
521 if (connection_backoff_ms_ > kMaxConnectionBackoffMs)
522 connection_backoff_ms_ = kMaxConnectionBackoffMs;
523 }
524
ResetConnectionBackoff()525 void ProbesProducer::ResetConnectionBackoff() {
526 connection_backoff_ms_ = kInitialConnectionBackoffMs;
527 }
528
529 } // namespace perfetto
530