xref: /aosp_15_r20/external/perfetto/src/traced/service/builtin_producer.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2019 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/service/builtin_producer.h"
18 
19 #include <sys/types.h>
20 
21 #include "perfetto/base/build_config.h"
22 #include "perfetto/base/logging.h"
23 #include "perfetto/base/proc_utils.h"
24 #include "perfetto/ext/base/metatrace.h"
25 #include "perfetto/ext/base/utils.h"
26 #include "perfetto/ext/base/weak_ptr.h"
27 #include "perfetto/ext/tracing/core/basic_types.h"
28 #include "perfetto/ext/tracing/core/client_identity.h"
29 #include "perfetto/ext/tracing/core/trace_writer.h"
30 #include "perfetto/ext/tracing/core/tracing_service.h"
31 #include "perfetto/tracing/core/data_source_config.h"
32 #include "perfetto/tracing/core/data_source_descriptor.h"
33 #include "src/tracing/service/metatrace_writer.h"
34 
35 #include "protos/perfetto/config/android/android_sdk_sysprop_guard_config.pbzero.h"
36 
37 // This translation unit is only ever used in Android in-tree builds.
38 // These producers are here  to dynamically start heapprofd and other services
39 // via sysprops when a trace that requests them is active. That can only happen
40 // in in-tree builds of Android.
41 
42 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
43 #include <sys/system_properties.h>
44 #endif
45 
46 namespace perfetto {
47 
48 namespace {
49 
50 constexpr char kHeapprofdDataSourceName[] = "android.heapprofd";
51 constexpr char kJavaHprofDataSourceName[] = "android.java_hprof";
52 constexpr char kJavaHprofOomDataSourceName[] = "android.java_hprof.oom";
53 constexpr char kTracedPerfDataSourceName[] = "linux.perf";
54 constexpr char kLazyHeapprofdPropertyName[] = "traced.lazy.heapprofd";
55 constexpr char kLazyTracedPerfPropertyName[] = "traced.lazy.traced_perf";
56 constexpr char kJavaHprofOomActivePropertyName[] =
57     "traced.oome_heap_session.count";
58 
59 constexpr char kAndroidSdkSyspropGuardDataSourceName[] =
60     "android.sdk_sysprop_guard";
61 constexpr char kPerfettoSdkSyspropGuardGenerationPropertyName[] =
62     "debug.tracing.ctl.perfetto.sdk_sysprop_guard_generation";
63 constexpr char kHwuiSkiaBroadTracingPropertyName[] =
64     "debug.tracing.ctl.hwui.skia_tracing_enabled";
65 constexpr char kHwuiSkiaUsePerfettoPropertyName[] =
66     "debug.tracing.ctl.hwui.skia_use_perfetto_track_events";
67 constexpr char kHwuiSkiaPropertyPackageSeparator[] = ".";
68 constexpr char kSurfaceFlingerSkiaBroadTracingPropertyName[] =
69     "debug.tracing.ctl.renderengine.skia_tracing_enabled";
70 constexpr char kSurfaceFlingerSkiaUsePerfettoPropertyName[] =
71     "debug.tracing.ctl.renderengine.skia_use_perfetto_track_events";
72 
73 }  // namespace
74 
BuiltinProducer(base::TaskRunner * task_runner,uint32_t lazy_stop_delay_ms)75 BuiltinProducer::BuiltinProducer(base::TaskRunner* task_runner,
76                                  uint32_t lazy_stop_delay_ms)
77     : task_runner_(task_runner), weak_factory_(this) {
78   lazy_heapprofd_.stop_delay_ms = lazy_stop_delay_ms;
79   lazy_traced_perf_.stop_delay_ms = lazy_stop_delay_ms;
80 }
81 
~BuiltinProducer()82 BuiltinProducer::~BuiltinProducer() {
83   if (!lazy_heapprofd_.instance_ids.empty())
84     SetAndroidProperty(kLazyHeapprofdPropertyName, "");
85   if (!lazy_traced_perf_.instance_ids.empty())
86     SetAndroidProperty(kLazyTracedPerfPropertyName, "");
87   if (!java_hprof_oome_instances_.empty())
88     SetAndroidProperty(kJavaHprofOomActivePropertyName, "");
89 }
90 
ConnectInProcess(TracingService * svc)91 void BuiltinProducer::ConnectInProcess(TracingService* svc) {
92 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
93   // TODO(primiano): ConnectProducer should take a base::PlatformProcessId not
94   // pid_t, as they are different on Windows. But that is a larger refactoring
95   // and not worth given this is the only use case where it clashes.
96   const pid_t cur_proc_id = 0;
97 #else
98   const pid_t cur_proc_id = base::GetProcessId();
99 #endif
100   endpoint_ = svc->ConnectProducer(
101       this, ClientIdentity(base::GetCurrentUserId(), cur_proc_id), "traced",
102       /*shared_memory_size_hint_bytes=*/16 * 1024, /*in_process=*/true,
103       TracingService::ProducerSMBScrapingMode::kDisabled,
104       /*shared_memory_page_size_hint_bytes=*/4096);
105 }
106 
OnConnect()107 void BuiltinProducer::OnConnect() {
108   DataSourceDescriptor metatrace_dsd;
109   metatrace_dsd.set_name(MetatraceWriter::kDataSourceName);
110   metatrace_dsd.set_will_notify_on_stop(true);
111   endpoint_->RegisterDataSource(metatrace_dsd);
112   {
113     DataSourceDescriptor lazy_heapprofd_dsd;
114     lazy_heapprofd_dsd.set_name(kHeapprofdDataSourceName);
115     endpoint_->RegisterDataSource(lazy_heapprofd_dsd);
116   }
117   {
118     DataSourceDescriptor lazy_java_hprof_dsd;
119     lazy_java_hprof_dsd.set_name(kJavaHprofDataSourceName);
120     endpoint_->RegisterDataSource(lazy_java_hprof_dsd);
121   }
122   {
123     DataSourceDescriptor lazy_traced_perf_dsd;
124     lazy_traced_perf_dsd.set_name(kTracedPerfDataSourceName);
125     endpoint_->RegisterDataSource(lazy_traced_perf_dsd);
126   }
127   {
128     DataSourceDescriptor java_hprof_oome_dsd;
129     java_hprof_oome_dsd.set_name(kJavaHprofOomDataSourceName);
130     endpoint_->RegisterDataSource(java_hprof_oome_dsd);
131   }
132   {
133     DataSourceDescriptor track_event_dsd;
134     track_event_dsd.set_name(kAndroidSdkSyspropGuardDataSourceName);
135     endpoint_->RegisterDataSource(track_event_dsd);
136   }
137 }
138 
SetupDataSource(DataSourceInstanceID ds_id,const DataSourceConfig & ds_config)139 void BuiltinProducer::SetupDataSource(DataSourceInstanceID ds_id,
140                                       const DataSourceConfig& ds_config) {
141   if (ds_config.name() == kHeapprofdDataSourceName ||
142       ds_config.name() == kJavaHprofDataSourceName) {
143     SetAndroidProperty(kLazyHeapprofdPropertyName, "1");
144     lazy_heapprofd_.generation++;
145     lazy_heapprofd_.instance_ids.emplace(ds_id);
146     return;
147   }
148 
149   if (ds_config.name() == kTracedPerfDataSourceName) {
150     SetAndroidProperty(kLazyTracedPerfPropertyName, "1");
151     lazy_traced_perf_.generation++;
152     lazy_traced_perf_.instance_ids.emplace(ds_id);
153     return;
154   }
155 
156   if (ds_config.name() == kJavaHprofOomDataSourceName) {
157     java_hprof_oome_instances_.emplace(ds_id);
158     SetAndroidProperty(kJavaHprofOomActivePropertyName,
159                        std::to_string(java_hprof_oome_instances_.size()));
160     return;
161   }
162 
163   // TODO(b/281329340): delete this when no longer needed.
164   if (ds_config.name() == kAndroidSdkSyspropGuardDataSourceName) {
165     protos::pbzero::AndroidSdkSyspropGuardConfig::Decoder sysprop_guard_config(
166         ds_config.android_sdk_sysprop_guard_config_raw());
167     std::vector<std::string> hwui_package_name_filter;
168     for (auto package = sysprop_guard_config.hwui_package_name_filter();
169          package; ++package) {
170       hwui_package_name_filter.emplace_back((*package).ToStdString());
171     }
172 
173     bool increase_generation = false;
174 
175     // SurfaceFlinger / RenderEngine
176     if (sysprop_guard_config.surfaceflinger_skia_track_events() &&
177         !android_sdk_sysprop_guard_state_.surfaceflinger_initialized) {
178       SetAndroidProperty(kSurfaceFlingerSkiaBroadTracingPropertyName, "true");
179       SetAndroidProperty(kSurfaceFlingerSkiaUsePerfettoPropertyName, "true");
180       android_sdk_sysprop_guard_state_.surfaceflinger_initialized = true;
181       increase_generation = true;
182     }
183 
184     // HWUI apps
185     if (sysprop_guard_config.hwui_skia_track_events()) {
186       if (hwui_package_name_filter.size() > 0) {
187         // Set per-app flags
188         for (std::string package : hwui_package_name_filter) {
189           if (android_sdk_sysprop_guard_state_.hwui_packages_initialized.count(
190                   package) == 0) {
191             SetAndroidProperty(
192                 kHwuiSkiaBroadTracingPropertyName +
193                     (kHwuiSkiaPropertyPackageSeparator + package),
194                 "true");
195             SetAndroidProperty(
196                 kHwuiSkiaUsePerfettoPropertyName +
197                     (kHwuiSkiaPropertyPackageSeparator + package),
198                 "true");
199             android_sdk_sysprop_guard_state_.hwui_packages_initialized.insert(
200                 package);
201             increase_generation = true;
202           }
203         }
204       } else if (!android_sdk_sysprop_guard_state_.hwui_globally_initialized) {
205         // Set global flag
206         SetAndroidProperty(kHwuiSkiaBroadTracingPropertyName, "true");
207         SetAndroidProperty(kHwuiSkiaUsePerfettoPropertyName, "true");
208         android_sdk_sysprop_guard_state_.hwui_globally_initialized = true;
209         increase_generation = true;
210       }
211     }
212 
213     if (increase_generation) {
214       android_sdk_sysprop_guard_state_.generation++;
215       SetAndroidProperty(
216           kPerfettoSdkSyspropGuardGenerationPropertyName,
217           std::to_string(android_sdk_sysprop_guard_state_.generation));
218     }
219 
220     return;
221   }
222 }
223 
StartDataSource(DataSourceInstanceID ds_id,const DataSourceConfig & ds_config)224 void BuiltinProducer::StartDataSource(DataSourceInstanceID ds_id,
225                                       const DataSourceConfig& ds_config) {
226   // We slightly rely on the fact that since this producer is in-process for
227   // enabling metatrace early (relative to producers that are notified via IPC).
228   if (ds_config.name() == MetatraceWriter::kDataSourceName) {
229     auto writer = endpoint_->CreateTraceWriter(
230         static_cast<BufferID>(ds_config.target_buffer()));
231 
232     auto it_and_inserted = metatrace_.writers.emplace(
233         std::piecewise_construct, std::make_tuple(ds_id), std::make_tuple());
234     PERFETTO_DCHECK(it_and_inserted.second);
235     // Note: only the first concurrent writer will actually be active.
236     metatrace_.writers[ds_id].Enable(task_runner_, std::move(writer),
237                                      metatrace::TAG_ANY);
238   }
239 }
240 
StopDataSource(DataSourceInstanceID ds_id)241 void BuiltinProducer::StopDataSource(DataSourceInstanceID ds_id) {
242   auto meta_it = metatrace_.writers.find(ds_id);
243   if (meta_it != metatrace_.writers.end()) {
244     // Synchronously re-flush the metatrace writer to record more of the
245     // teardown interactions, then ack the stop.
246     meta_it->second.WriteAllAndFlushTraceWriter([] {});
247     metatrace_.writers.erase(meta_it);
248     endpoint_->NotifyDataSourceStopped(ds_id);
249     return;
250   }
251 
252   MaybeInitiateLazyStop(ds_id, &lazy_heapprofd_, kLazyHeapprofdPropertyName);
253   MaybeInitiateLazyStop(ds_id, &lazy_traced_perf_, kLazyTracedPerfPropertyName);
254 
255   auto oome_it = java_hprof_oome_instances_.find(ds_id);
256   if (oome_it != java_hprof_oome_instances_.end()) {
257     java_hprof_oome_instances_.erase(oome_it);
258     SetAndroidProperty(kJavaHprofOomActivePropertyName,
259                        std::to_string(java_hprof_oome_instances_.size()));
260   }
261 }
262 
MaybeInitiateLazyStop(DataSourceInstanceID ds_id,LazyAndroidDaemonState * lazy_state,const char * prop_name)263 void BuiltinProducer::MaybeInitiateLazyStop(DataSourceInstanceID ds_id,
264                                             LazyAndroidDaemonState* lazy_state,
265                                             const char* prop_name) {
266   auto lazy_it = lazy_state->instance_ids.find(ds_id);
267   if (lazy_it != lazy_state->instance_ids.end()) {
268     lazy_state->instance_ids.erase(lazy_it);
269 
270     // if no more sessions - stop daemon after a delay
271     if (lazy_state->instance_ids.empty()) {
272       uint64_t cur_generation = lazy_state->generation;
273       auto weak_this = weak_factory_.GetWeakPtr();
274       task_runner_->PostDelayedTask(
275           [weak_this, cur_generation, lazy_state, prop_name] {
276             if (!weak_this)
277               return;
278             // |lazy_state| should be valid if the |weak_this| is still valid
279             if (lazy_state->generation == cur_generation)
280               weak_this->SetAndroidProperty(prop_name, "");
281           },
282           lazy_state->stop_delay_ms);
283     }
284   }
285 }
286 
Flush(FlushRequestID flush_id,const DataSourceInstanceID * ds_ids,size_t num_ds_ids,FlushFlags)287 void BuiltinProducer::Flush(FlushRequestID flush_id,
288                             const DataSourceInstanceID* ds_ids,
289                             size_t num_ds_ids,
290                             FlushFlags) {
291   for (size_t i = 0; i < num_ds_ids; i++) {
292     auto meta_it = metatrace_.writers.find(ds_ids[i]);
293     if (meta_it != metatrace_.writers.end()) {
294       meta_it->second.WriteAllAndFlushTraceWriter([] {});
295     }
296     // nothing to be done for lazy sources
297   }
298   endpoint_->NotifyFlushComplete(flush_id);
299 }
300 
SetAndroidProperty(const std::string & name,const std::string & value)301 bool BuiltinProducer::SetAndroidProperty(const std::string& name,
302                                          const std::string& value) {
303 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
304   return __system_property_set(name.c_str(), value.c_str()) == 0;
305 #else
306   // Allow this to be mocked out for tests on other platforms.
307   base::ignore_result(name);
308   base::ignore_result(value);
309   return true;
310 #endif
311 }
312 
313 }  // namespace perfetto
314