1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h"
6 
7 #include <limits>
8 #include <set>
9 
10 #include "base/bind_helpers.h"
11 #include "base/debug/leak_annotations.h"
12 #include "base/hash/hash.h"
13 #include "base/memory/ptr_util.h"
14 #include "base/no_destructor.h"
15 #include "base/process/process.h"
16 #include "base/process/process_handle.h"
17 #include "base/profiler/sampling_profiler_thread_token.h"
18 #include "base/profiler/stack_sampling_profiler.h"
19 #include "base/strings/strcat.h"
20 #include "base/task/thread_pool/thread_pool_instance.h"
21 #include "base/threading/sequence_local_storage_slot.h"
22 #include "base/trace_event/trace_event.h"
23 #include "build/build_config.h"
24 #include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
25 #include "services/tracing/public/cpp/perfetto/producer_client.h"
26 #include "third_party/perfetto/protos/perfetto/trace/interned_data/interned_data.pbzero.h"
27 #include "third_party/perfetto/protos/perfetto/trace/profiling/profile_common.pbzero.h"
28 #include "third_party/perfetto/protos/perfetto/trace/profiling/profile_packet.pbzero.h"
29 #include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h"
30 #include "third_party/perfetto/protos/perfetto/trace/track_event/process_descriptor.pbzero.h"
31 #include "third_party/perfetto/protos/perfetto/trace/track_event/thread_descriptor.pbzero.h"
32 
33 #if defined(OS_ANDROID)
34 #include "base/android/reached_code_profiler.h"
35 #endif
36 
37 #if defined(OS_ANDROID) && BUILDFLAG(CAN_UNWIND_WITH_CFI_TABLE) && \
38     defined(OFFICIAL_BUILD)
39 #include <dlfcn.h>
40 
41 #include "base/trace_event/cfi_backtrace_android.h"
42 #include "services/tracing/public/cpp/stack_sampling/stack_sampler_android.h"
43 #endif
44 
45 using StreamingProfilePacketHandle =
46     protozero::MessageHandle<perfetto::protos::pbzero::StreamingProfilePacket>;
47 
48 namespace tracing {
49 
50 namespace {
51 
52 class TracingSamplerProfilerDataSource
53     : public PerfettoTracedProcess::DataSourceBase {
54  public:
Get()55   static TracingSamplerProfilerDataSource* Get() {
56     static base::NoDestructor<TracingSamplerProfilerDataSource> instance;
57     return instance.get();
58   }
59 
TracingSamplerProfilerDataSource()60   TracingSamplerProfilerDataSource()
61       : DataSourceBase(mojom::kSamplerProfilerSourceName) {}
62 
~TracingSamplerProfilerDataSource()63   ~TracingSamplerProfilerDataSource() override { NOTREACHED(); }
64 
RegisterProfiler(TracingSamplerProfiler * profiler)65   void RegisterProfiler(TracingSamplerProfiler* profiler) {
66     base::AutoLock lock(lock_);
67     if (!profilers_.insert(profiler).second) {
68       return;
69     }
70 
71     if (is_started_) {
72       profiler->StartTracing(
73           producer_->CreateTraceWriter(data_source_config_.target_buffer()),
74           data_source_config_.chrome_config().privacy_filtering_enabled());
75     } else if (is_startup_tracing_) {
76       profiler->StartTracing(nullptr, /*should_enable_filtering=*/true);
77     }
78   }
79 
UnregisterProfiler(TracingSamplerProfiler * profiler)80   void UnregisterProfiler(TracingSamplerProfiler* profiler) {
81     base::AutoLock lock(lock_);
82     if (!profilers_.erase(profiler) || !(is_started_ || is_startup_tracing_)) {
83       return;
84     }
85 
86     profiler->StopTracing();
87   }
88 
89   // PerfettoTracedProcess::DataSourceBase implementation, called by
90   // ProducerClient.
StartTracing(PerfettoProducer * producer,const perfetto::DataSourceConfig & data_source_config)91   void StartTracing(
92       PerfettoProducer* producer,
93       const perfetto::DataSourceConfig& data_source_config) override {
94     base::AutoLock lock(lock_);
95     DCHECK(!is_started_);
96     is_started_ = true;
97     is_startup_tracing_ = false;
98     data_source_config_ = data_source_config;
99 
100     bool should_enable_filtering =
101         data_source_config.chrome_config().privacy_filtering_enabled();
102 
103     for (auto* profiler : profilers_) {
104       profiler->StartTracing(
105           producer->CreateTraceWriter(data_source_config.target_buffer()),
106           should_enable_filtering);
107     }
108   }
109 
StopTracing(base::OnceClosure stop_complete_callback)110   void StopTracing(base::OnceClosure stop_complete_callback) override {
111     base::AutoLock lock(lock_);
112     DCHECK(is_started_);
113     is_started_ = false;
114     is_startup_tracing_ = false;
115     producer_ = nullptr;
116 
117     for (auto* profiler : profilers_) {
118       profiler->StopTracing();
119     }
120 
121     std::move(stop_complete_callback).Run();
122   }
123 
Flush(base::RepeatingClosure flush_complete_callback)124   void Flush(base::RepeatingClosure flush_complete_callback) override {
125     flush_complete_callback.Run();
126   }
127 
SetupStartupTracing(PerfettoProducer * producer,const base::trace_event::TraceConfig & trace_config,bool privacy_filtering_enabled)128   void SetupStartupTracing(PerfettoProducer* producer,
129                            const base::trace_event::TraceConfig& trace_config,
130                            bool privacy_filtering_enabled) override {
131     bool enable_sampler_profiler = trace_config.IsCategoryGroupEnabled(
132         TRACE_DISABLED_BY_DEFAULT("cpu_profiler"));
133     if (!enable_sampler_profiler)
134       return;
135 
136     base::AutoLock lock(lock_);
137     if (is_started_) {
138       return;
139     }
140     is_startup_tracing_ = true;
141     for (auto* profiler : profilers_) {
142       // Enable filtering for startup tracing always to be safe.
143       profiler->StartTracing(nullptr, /*should_enable_filtering=*/true);
144     }
145   }
146 
AbortStartupTracing()147   void AbortStartupTracing() override {
148     base::AutoLock lock(lock_);
149     if (!is_startup_tracing_) {
150       return;
151     }
152     for (auto* profiler : profilers_) {
153       // Enable filtering for startup tracing always to be safe.
154       profiler->StartTracing(nullptr, /*should_enable_filtering=*/true);
155     }
156     is_startup_tracing_ = false;
157   }
158 
ClearIncrementalState()159   void ClearIncrementalState() override {
160     incremental_state_reset_id_.fetch_add(1u, std::memory_order_relaxed);
161   }
162 
GetIncrementalStateResetID()163   static uint32_t GetIncrementalStateResetID() {
164     return incremental_state_reset_id_.load(std::memory_order_relaxed);
165   }
166 
167  private:
168   base::Lock lock_;  // Protects subsequent members.
169   std::set<TracingSamplerProfiler*> profilers_;
170   bool is_startup_tracing_ = false;
171   bool is_started_ = false;
172   perfetto::DataSourceConfig data_source_config_;
173 
174   static std::atomic<uint32_t> incremental_state_reset_id_;
175 };
176 
177 // static
178 std::atomic<uint32_t>
179     TracingSamplerProfilerDataSource::incremental_state_reset_id_{0};
180 
181 base::SequenceLocalStorageSlot<TracingSamplerProfiler>&
GetSequenceLocalStorageProfilerSlot()182 GetSequenceLocalStorageProfilerSlot() {
183   static base::NoDestructor<
184       base::SequenceLocalStorageSlot<TracingSamplerProfiler>>
185       storage;
186   return *storage;
187 }
188 
189 }  // namespace
190 
BufferedSample(base::TimeTicks ts,std::vector<base::Frame> && s)191 TracingSamplerProfiler::TracingProfileBuilder::BufferedSample::BufferedSample(
192     base::TimeTicks ts,
193     std::vector<base::Frame>&& s)
194     : timestamp(ts), sample(std::move(s)) {}
195 
196 TracingSamplerProfiler::TracingProfileBuilder::BufferedSample::
197     ~BufferedSample() = default;
198 
BufferedSample(TracingSamplerProfiler::TracingProfileBuilder::BufferedSample && other)199 TracingSamplerProfiler::TracingProfileBuilder::BufferedSample::BufferedSample(
200     TracingSamplerProfiler::TracingProfileBuilder::BufferedSample&& other)
201     : BufferedSample(other.timestamp, std::move(other.sample)) {}
202 
TracingProfileBuilder(base::PlatformThreadId sampled_thread_id,std::unique_ptr<perfetto::TraceWriter> trace_writer,bool should_enable_filtering,const base::RepeatingClosure & sample_callback_for_testing)203 TracingSamplerProfiler::TracingProfileBuilder::TracingProfileBuilder(
204     base::PlatformThreadId sampled_thread_id,
205     std::unique_ptr<perfetto::TraceWriter> trace_writer,
206     bool should_enable_filtering,
207     const base::RepeatingClosure& sample_callback_for_testing)
208     : sampled_thread_id_(sampled_thread_id),
209       trace_writer_(std::move(trace_writer)),
210       should_enable_filtering_(should_enable_filtering),
211       sample_callback_for_testing_(sample_callback_for_testing) {}
212 
~TracingProfileBuilder()213 TracingSamplerProfiler::TracingProfileBuilder::~TracingProfileBuilder() {
214   // Deleting a TraceWriter can end up triggering a Mojo call which calls
215   // TaskRunnerHandle::Get() and isn't safe on thread shutdown, which is when
216   // TracingProfileBuilder gets destructed, so we make sure this happens on
217   // a different sequence.
218   if (base::ThreadPoolInstance::Get()) {
219     PerfettoTracedProcess::GetTaskRunner()->GetOrCreateTaskRunner()->DeleteSoon(
220         FROM_HERE, std::move(trace_writer_));
221   } else {
222     // Intentionally leak; we have no way of safely destroying this at this
223     // point.
224     ANNOTATE_LEAKING_OBJECT_PTR(trace_writer_.get());
225     trace_writer_.release();
226   }
227 }
228 
229 base::ModuleCache*
GetModuleCache()230 TracingSamplerProfiler::TracingProfileBuilder::GetModuleCache() {
231   return &module_cache_;
232 }
233 
OnSampleCompleted(std::vector<base::Frame> frames,base::TimeTicks sample_timestamp)234 void TracingSamplerProfiler::TracingProfileBuilder::OnSampleCompleted(
235     std::vector<base::Frame> frames,
236     base::TimeTicks sample_timestamp) {
237   base::AutoLock l(trace_writer_lock_);
238   if (!trace_writer_) {
239     if (buffered_samples_.size() < kMaxBufferedSamples) {
240       buffered_samples_.emplace_back(
241           BufferedSample(sample_timestamp, std::move(frames)));
242     }
243     return;
244   }
245   if (!buffered_samples_.empty()) {
246     for (const auto& sample : buffered_samples_) {
247       WriteSampleToTrace(sample);
248     }
249     buffered_samples_.clear();
250   }
251   WriteSampleToTrace(BufferedSample(sample_timestamp, std::move(frames)));
252 
253   if (sample_callback_for_testing_) {
254     sample_callback_for_testing_.Run();
255   }
256 }
257 
WriteSampleToTrace(const TracingSamplerProfiler::TracingProfileBuilder::BufferedSample & sample)258 void TracingSamplerProfiler::TracingProfileBuilder::WriteSampleToTrace(
259     const TracingSamplerProfiler::TracingProfileBuilder::BufferedSample&
260         sample) {
261   const auto& frames = sample.sample;
262   auto reset_id =
263       TracingSamplerProfilerDataSource::GetIncrementalStateResetID();
264   if (reset_id != last_incremental_state_reset_id_) {
265     reset_incremental_state_ = true;
266     last_incremental_state_reset_id_ = reset_id;
267   }
268 
269   if (reset_incremental_state_) {
270     interned_callstacks_.ResetEmittedState();
271     interned_frames_.ResetEmittedState();
272     interned_frame_names_.ResetEmittedState();
273     interned_module_names_.ResetEmittedState();
274     interned_module_ids_.ResetEmittedState();
275     interned_modules_.ResetEmittedState();
276 
277     auto trace_packet = trace_writer_->NewTracePacket();
278     trace_packet->set_sequence_flags(
279         perfetto::protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED);
280 
281     // Note: Make sure ThreadDescriptors we emit here won't cause
282     // metadata events to be emitted from the JSON exporter which conflict
283     // with the metadata events emitted by the regular TrackEventDataSource.
284     auto* thread_descriptor = trace_packet->set_thread_descriptor();
285     thread_descriptor->set_pid(base::GetCurrentProcId());
286     thread_descriptor->set_tid(sampled_thread_id_);
287     last_timestamp_ = sample.timestamp;
288     thread_descriptor->set_reference_timestamp_us(
289         last_timestamp_.since_origin().InMicroseconds());
290     reset_incremental_state_ = false;
291   }
292 
293   int32_t current_process_priority = base::Process::Current().GetPriority();
294   if (current_process_priority != last_emitted_process_priority_) {
295     last_emitted_process_priority_ = current_process_priority;
296     auto trace_packet = trace_writer_->NewTracePacket();
297     auto* process_descriptor = trace_packet->set_process_descriptor();
298     process_descriptor->set_pid(base::GetCurrentProcId());
299     process_descriptor->set_process_priority(current_process_priority);
300   }
301 
302   auto trace_packet = trace_writer_->NewTracePacket();
303   // Delta encoded timestamps and interned data require incremental state.
304   trace_packet->set_sequence_flags(
305       perfetto::protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE);
306   auto callstack_id = GetCallstackIDAndMaybeEmit(frames, &trace_packet);
307   auto* streaming_profile_packet = trace_packet->set_streaming_profile_packet();
308   streaming_profile_packet->add_callstack_iid(callstack_id);
309   streaming_profile_packet->add_timestamp_delta_us(
310       (sample.timestamp - last_timestamp_).InMicroseconds());
311   last_timestamp_ = sample.timestamp;
312 }
313 
SetTraceWriter(std::unique_ptr<perfetto::TraceWriter> writer)314 void TracingSamplerProfiler::TracingProfileBuilder::SetTraceWriter(
315     std::unique_ptr<perfetto::TraceWriter> writer) {
316   base::AutoLock l(trace_writer_lock_);
317   trace_writer_ = std::move(writer);
318 }
319 
320 InterningID
GetCallstackIDAndMaybeEmit(const std::vector<base::Frame> & frames,perfetto::TraceWriter::TracePacketHandle * trace_packet)321 TracingSamplerProfiler::TracingProfileBuilder::GetCallstackIDAndMaybeEmit(
322     const std::vector<base::Frame>& frames,
323     perfetto::TraceWriter::TracePacketHandle* trace_packet) {
324   size_t ip_hash = 0;
325   for (const auto& frame : frames) {
326     ip_hash = base::HashInts(ip_hash, frame.instruction_pointer);
327   }
328 
329   InterningIndexEntry interned_callstack =
330       interned_callstacks_.LookupOrAdd(ip_hash);
331 
332   if (interned_callstack.was_emitted)
333     return interned_callstack.id;
334 
335   auto* interned_data = (*trace_packet)->set_interned_data();
336 
337   std::vector<InterningID> frame_ids;
338   for (const auto& frame : frames) {
339     std::string frame_name;
340     std::string module_name;
341     std::string module_id;
342     uintptr_t rel_pc = 0;
343 
344 #if defined(OS_ANDROID) && BUILDFLAG(CAN_UNWIND_WITH_CFI_TABLE) && \
345     defined(OFFICIAL_BUILD)
346     Dl_info info = {};
347     // For chrome address we do not have symbols on the binary. So, just write
348     // the offset address. For addresses on framework libraries, symbolize
349     // and write the function name.
350     if (frame.instruction_pointer == 0) {
351       frame_name = "Scanned";
352     } else if (base::trace_event::CFIBacktraceAndroid::is_chrome_address(
353                    frame.instruction_pointer)) {
354       rel_pc = frame.instruction_pointer -
355                base::trace_event::CFIBacktraceAndroid::executable_start_addr();
356     } else if (dladdr(reinterpret_cast<void*>(frame.instruction_pointer),
357                       &info) != 0) {
358       // TODO(ssid): Add offset and module debug id if symbol was not resolved
359       // in case this might be useful to send report to vendors.
360       if (info.dli_sname)
361         frame_name = info.dli_sname;
362       if (info.dli_fname)
363         module_name = info.dli_fname;
364     }
365 
366     if (frame.module) {
367       module_id = frame.module->GetId();
368       if (module_name.empty())
369         module_name = frame.module->GetDebugBasename().MaybeAsASCII();
370     }
371 
372     // If no module is available, then name it unknown. Adding PC would be
373     // useless anyway.
374     if (module_name.empty()) {
375       DCHECK(!base::trace_event::CFIBacktraceAndroid::is_chrome_address(
376           frame.instruction_pointer));
377       frame_name = "Unknown";
378       rel_pc = 0;
379     }
380 #else
381     if (frame.module) {
382       module_name = frame.module->GetDebugBasename().MaybeAsASCII();
383       module_id = frame.module->GetId();
384       rel_pc = frame.instruction_pointer - frame.module->GetBaseAddress();
385     } else {
386       module_name = module_id = "";
387       frame_name = "Unknown";
388     }
389 #endif
390 
391     MangleModuleIDIfNeeded(&module_id);
392 
393     // We never emit frame names in privacy filtered mode.
394     bool should_emit_frame_names =
395         !frame_name.empty() && !should_enable_filtering_;
396 
397     if (should_enable_filtering_ && !rel_pc && frame.module) {
398       rel_pc = frame.instruction_pointer - frame.module->GetBaseAddress();
399     }
400 
401     InterningIndexEntry interned_frame;
402     if (should_emit_frame_names) {
403       interned_frame =
404           interned_frames_.LookupOrAdd(std::make_pair(frame_name, module_id));
405     } else {
406       interned_frame =
407           interned_frames_.LookupOrAdd(std::make_pair(rel_pc, module_id));
408     }
409 
410     if (!interned_frame.was_emitted) {
411       InterningIndexEntry interned_frame_name;
412       if (should_emit_frame_names) {
413         interned_frame_name = interned_frame_names_.LookupOrAdd(frame_name);
414         if (!interned_frame_name.was_emitted) {
415           auto* frame_name_entry = interned_data->add_function_names();
416           frame_name_entry->set_iid(interned_frame_name.id);
417           frame_name_entry->set_str(
418               reinterpret_cast<const uint8_t*>(frame_name.data()),
419               frame_name.length());
420         }
421       }
422 
423       InterningIndexEntry interned_module;
424       if (frame.module) {
425         interned_module =
426             interned_modules_.LookupOrAdd(frame.module->GetBaseAddress());
427         if (!interned_module.was_emitted) {
428           InterningIndexEntry interned_module_id =
429               interned_module_ids_.LookupOrAdd(module_id);
430           if (!interned_module_id.was_emitted) {
431             auto* module_id_entry = interned_data->add_build_ids();
432             module_id_entry->set_iid(interned_module_id.id);
433             module_id_entry->set_str(
434                 reinterpret_cast<const uint8_t*>(module_id.data()),
435                 module_id.length());
436           }
437 
438           InterningIndexEntry interned_module_name =
439               interned_module_names_.LookupOrAdd(module_name);
440           if (!interned_module_name.was_emitted) {
441             auto* module_name_entry = interned_data->add_mapping_paths();
442             module_name_entry->set_iid(interned_module_name.id);
443             module_name_entry->set_str(
444                 reinterpret_cast<const uint8_t*>(module_name.data()),
445                 module_name.length());
446           }
447           auto* module_entry = interned_data->add_mappings();
448           module_entry->set_iid(interned_module.id);
449           module_entry->set_build_id(interned_module_id.id);
450           module_entry->add_path_string_ids(interned_module_name.id);
451         }
452       }
453 
454       auto* frame_entry = interned_data->add_frames();
455       frame_entry->set_iid(interned_frame.id);
456       if (should_emit_frame_names) {
457         frame_entry->set_function_name_id(interned_frame_name.id);
458       } else {
459         frame_entry->set_rel_pc(rel_pc);
460       }
461       if (frame.module) {
462         frame_entry->set_mapping_id(interned_module.id);
463       }
464     }
465 
466     frame_ids.push_back(interned_frame.id);
467   }
468 
469   auto* callstack_entry = interned_data->add_callstacks();
470   callstack_entry->set_iid(interned_callstack.id);
471   for (auto& frame_id : frame_ids)
472     callstack_entry->add_frame_ids(frame_id);
473 
474   return interned_callstack.id;
475 }
476 
477 // static
MangleModuleIDIfNeeded(std::string * module_id)478 void TracingSamplerProfiler::MangleModuleIDIfNeeded(std::string* module_id) {
479 #if defined(OS_ANDROID) || defined(OS_LINUX)
480   // Linux ELF module IDs are 160bit integers, which we need to mangle
481   // down to 128bit integers to match the id that Breakpad outputs.
482   // Example on version '66.0.3359.170' x64:
483   //   Build-ID: "7f0715c2 86f8 b16c 10e4ad349cda3b9b 56c7a773
484   //   Debug-ID  "C215077F F886 6CB1 10E4AD349CDA3B9B 0"
485   if (module_id->size() >= 32) {
486     *module_id =
487         base::StrCat({module_id->substr(6, 2), module_id->substr(4, 2),
488                       module_id->substr(2, 2), module_id->substr(0, 2),
489                       module_id->substr(10, 2), module_id->substr(8, 2),
490                       module_id->substr(14, 2), module_id->substr(12, 2),
491                       module_id->substr(16, 16), "0"});
492   }
493 #endif
494 }
495 
496 // static
497 std::unique_ptr<TracingSamplerProfiler>
CreateOnMainThread()498 TracingSamplerProfiler::CreateOnMainThread() {
499   return std::make_unique<TracingSamplerProfiler>(
500       base::GetSamplingProfilerCurrentThreadToken());
501 }
502 
503 // static
CreateOnChildThread()504 void TracingSamplerProfiler::CreateOnChildThread() {
505   base::SequenceLocalStorageSlot<TracingSamplerProfiler>& slot =
506       GetSequenceLocalStorageProfilerSlot();
507   if (slot)
508     return;
509 
510   slot.emplace(base::GetSamplingProfilerCurrentThreadToken());
511 }
512 
513 // static
DeleteOnChildThreadForTesting()514 void TracingSamplerProfiler::DeleteOnChildThreadForTesting() {
515   GetSequenceLocalStorageProfilerSlot().reset();
516 }
517 
518 // static
RegisterDataSource()519 void TracingSamplerProfiler::RegisterDataSource() {
520   PerfettoTracedProcess::Get()->AddDataSource(
521       TracingSamplerProfilerDataSource::Get());
522 }
523 
524 // static
StartTracingForTesting(PerfettoProducer * producer)525 void TracingSamplerProfiler::StartTracingForTesting(
526     PerfettoProducer* producer) {
527   TracingSamplerProfilerDataSource::Get()->StartTracingWithID(
528       1, producer, perfetto::DataSourceConfig());
529 }
530 
531 // static
SetupStartupTracingForTesting()532 void TracingSamplerProfiler::SetupStartupTracingForTesting() {
533   base::trace_event::TraceConfig config(
534       TRACE_DISABLED_BY_DEFAULT("cpu_profiler"),
535       base::trace_event::TraceRecordMode::RECORD_UNTIL_FULL);
536   TracingSamplerProfilerDataSource::Get()->SetupStartupTracing(
537       /*producer=*/nullptr, config, /*privacy_filtering_enabled=*/false);
538 }
539 
540 // static
StopTracingForTesting()541 void TracingSamplerProfiler::StopTracingForTesting() {
542   TracingSamplerProfilerDataSource::Get()->StopTracing(base::DoNothing());
543 }
544 
TracingSamplerProfiler(base::SamplingProfilerThreadToken sampled_thread_token)545 TracingSamplerProfiler::TracingSamplerProfiler(
546     base::SamplingProfilerThreadToken sampled_thread_token)
547     : sampled_thread_token_(sampled_thread_token) {
548   DCHECK_NE(sampled_thread_token_.id, base::kInvalidThreadId);
549   TracingSamplerProfilerDataSource::Get()->RegisterProfiler(this);
550 }
551 
~TracingSamplerProfiler()552 TracingSamplerProfiler::~TracingSamplerProfiler() {
553   TracingSamplerProfilerDataSource::Get()->UnregisterProfiler(this);
554 }
555 
SetSampleCallbackForTesting(const base::RepeatingClosure & sample_callback_for_testing)556 void TracingSamplerProfiler::SetSampleCallbackForTesting(
557     const base::RepeatingClosure& sample_callback_for_testing) {
558   base::AutoLock lock(lock_);
559   sample_callback_for_testing_ = sample_callback_for_testing;
560 }
561 
StartTracing(std::unique_ptr<perfetto::TraceWriter> trace_writer,bool should_enable_filtering)562 void TracingSamplerProfiler::StartTracing(
563     std::unique_ptr<perfetto::TraceWriter> trace_writer,
564     bool should_enable_filtering) {
565   base::AutoLock lock(lock_);
566   if (profiler_) {
567     if (trace_writer) {
568       profile_builder_->SetTraceWriter(std::move(trace_writer));
569     }
570     return;
571   }
572 
573 #if defined(OS_ANDROID)
574   // The sampler profiler would conflict with the reached code profiler if they
575   // run at the same time because they use the same signal to suspend threads.
576   if (base::android::IsReachedCodeProfilerEnabled())
577     return;
578 #endif
579 
580   base::StackSamplingProfiler::SamplingParams params;
581   params.samples_per_profile = std::numeric_limits<int>::max();
582   params.sampling_interval = base::TimeDelta::FromMilliseconds(50);
583   // If the sampled thread is stopped for too long for sampling then it is ok to
584   // get next sample at a later point of time. We do not want very accurate
585   // metrics when looking at traces.
586   params.keep_consistent_sampling_interval = false;
587 
588   auto profile_builder = std::make_unique<TracingProfileBuilder>(
589       sampled_thread_token_.id, std::move(trace_writer),
590       should_enable_filtering, sample_callback_for_testing_);
591   profile_builder_ = profile_builder.get();
592   // Create and start the stack sampling profiler.
593 #if defined(OS_ANDROID)
594 #if BUILDFLAG(CAN_UNWIND_WITH_CFI_TABLE) && defined(OFFICIAL_BUILD)
595   auto* module_cache = profile_builder->GetModuleCache();
596   profiler_ = std::make_unique<base::StackSamplingProfiler>(
597       params, std::move(profile_builder),
598       std::make_unique<StackSamplerAndroid>(sampled_thread_token_,
599                                             module_cache));
600   profiler_->Start();
601 #endif  // BUILDFLAG(CAN_UNWIND_WITH_CFI_TABLE) && defined(OFFICIAL_BUILD)
602 #else   // defined(OS_ANDROID)
603   profiler_ = std::make_unique<base::StackSamplingProfiler>(
604       sampled_thread_token_, params, std::move(profile_builder));
605   profiler_->Start();
606 #endif  // defined(OS_ANDROID)
607 }
608 
StopTracing()609 void TracingSamplerProfiler::StopTracing() {
610   base::AutoLock lock(lock_);
611   if (!profiler_) {
612     return;
613   }
614 
615   // Stop and release the stack sampling profiler.
616   profiler_->Stop();
617   profile_builder_ = nullptr;
618   profiler_.reset();
619 }
620 
621 }  // namespace tracing
622