1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
9 #include "base/android/jni_string.h"
10 #include "base/android/trace_event_binding.h"
11 #include "base/base_jni/TraceEvent_jni.h"
12 #include "base/metrics/histogram_macros.h"
13 #include "base/trace_event/base_tracing.h"
14 #include "base/tracing_buildflags.h"
16 #if BUILDFLAG(ENABLE_BASE_TRACING)
17 #include "base/trace_event/trace_event_impl.h" // no-presubmit-check
18 #include "third_party/perfetto/protos/perfetto/config/chrome/chrome_config.gen.h" // nogncheck
19 #endif // BUILDFLAG(ENABLE_BASE_TRACING)
24 #if BUILDFLAG(ENABLE_BASE_TRACING)
28 constexpr const char kAndroidViewHierarchyTraceCategory[] =
29 TRACE_DISABLED_BY_DEFAULT("android_view_hierarchy");
30 constexpr const char kAndroidViewHierarchyEventName[] = "AndroidView";
32 #if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
33 class TraceEnabledObserver : public perfetto::TrackEventSessionObserver {
35 static TraceEnabledObserver* GetInstance() {
36 static base::NoDestructor<TraceEnabledObserver> instance;
37 return instance.get();
40 // perfetto::TrackEventSessionObserver implementation
41 void OnSetup(const perfetto::DataSourceBase::SetupArgs& args) override {
42 trace_event::TraceConfig trace_config(
43 args.config->chrome_config().trace_config());
44 event_name_filtering_per_session_[args.internal_instance_index] =
45 trace_config.IsEventPackageNameFilterEnabled();
48 void OnStart(const perfetto::DataSourceBase::StartArgs&) override {
49 JNIEnv* env = base::android::AttachCurrentThread();
50 base::android::Java_TraceEvent_setEnabled(env, true);
51 base::android::Java_TraceEvent_setEventNameFilteringEnabled(
52 env, EventNameFilteringEnabled());
55 void OnStop(const perfetto::DataSourceBase::StopArgs& args) override {
56 event_name_filtering_per_session_.erase(args.internal_instance_index);
58 JNIEnv* env = base::android::AttachCurrentThread();
59 base::android::Java_TraceEvent_setEnabled(
60 env, !event_name_filtering_per_session_.empty());
61 base::android::Java_TraceEvent_setEventNameFilteringEnabled(
62 env, EventNameFilteringEnabled());
66 friend class base::NoDestructor<TraceEnabledObserver>;
67 TraceEnabledObserver() = default;
68 ~TraceEnabledObserver() override = default;
70 // Return true if event name filtering is requested by at least one tracing
72 bool EventNameFilteringEnabled() const {
73 bool event_name_filtering_enabled = false;
74 for (const auto& entry : event_name_filtering_per_session_) {
76 event_name_filtering_enabled = true;
79 return event_name_filtering_enabled;
82 std::unordered_map<uint32_t, bool> event_name_filtering_per_session_;
85 #else // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
87 class TraceEnabledObserver
88 : public trace_event::TraceLog::EnabledStateObserver {
90 ~TraceEnabledObserver() override = default;
92 // trace_event::TraceLog::EnabledStateObserver:
93 void OnTraceLogEnabled() override {
94 JNIEnv* env = base::android::AttachCurrentThread();
95 base::android::Java_TraceEvent_setEnabled(env, true);
96 if (base::trace_event::TraceLog::GetInstance()
97 ->GetCurrentTraceConfig()
98 .IsEventPackageNameFilterEnabled()) {
99 base::android::Java_TraceEvent_setEventNameFilteringEnabled(env, true);
103 void OnTraceLogDisabled() override {
104 JNIEnv* env = base::android::AttachCurrentThread();
105 base::android::Java_TraceEvent_setEnabled(env, false);
106 base::android::Java_TraceEvent_setEventNameFilteringEnabled(env, false);
109 #endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
113 static void JNI_TraceEvent_RegisterEnabledObserver(JNIEnv* env) {
114 #if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
115 base::android::Java_TraceEvent_setEnabled(env, base::TrackEvent::IsEnabled());
116 base::TrackEvent::AddSessionObserver(TraceEnabledObserver::GetInstance());
118 bool enabled = trace_event::TraceLog::GetInstance()->IsEnabled();
119 base::android::Java_TraceEvent_setEnabled(env, enabled);
120 trace_event::TraceLog::GetInstance()->AddOwnedEnabledStateObserver(
121 std::make_unique<TraceEnabledObserver>());
125 static jboolean JNI_TraceEvent_ViewHierarchyDumpEnabled(JNIEnv* env) {
126 static const unsigned char* enabled =
127 TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
128 kAndroidViewHierarchyTraceCategory);
132 static void JNI_TraceEvent_InitViewHierarchyDump(
135 const JavaParamRef<jobject>& obj) {
137 kAndroidViewHierarchyTraceCategory, kAndroidViewHierarchyEventName,
138 perfetto::TerminatingFlow::ProcessScoped(static_cast<uint64_t>(id)),
139 [&](perfetto::EventContext ctx) {
140 auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>();
141 auto* dump = event->set_android_view_dump();
142 Java_TraceEvent_dumpViewHierarchy(env, reinterpret_cast<jlong>(dump),
147 static jlong JNI_TraceEvent_StartActivityDump(JNIEnv* env,
148 const JavaParamRef<jstring>& name,
149 jlong dump_proto_ptr) {
150 auto* dump = reinterpret_cast<perfetto::protos::pbzero::AndroidViewDump*>(
152 auto* activity = dump->add_activity();
153 activity->set_name(ConvertJavaStringToUTF8(env, name));
154 return reinterpret_cast<jlong>(activity);
157 static void JNI_TraceEvent_AddViewDump(
163 const JavaParamRef<jstring>& class_name,
164 const JavaParamRef<jstring>& resource_name,
165 jlong activity_proto_ptr) {
166 auto* activity = reinterpret_cast<perfetto::protos::pbzero::AndroidActivity*>(
168 auto* view = activity->add_view();
170 view->set_parent_id(parent_id);
171 view->set_is_shown(is_shown);
172 view->set_is_dirty(is_dirty);
173 view->set_class_name(ConvertJavaStringToUTF8(env, class_name));
174 view->set_resource_name(ConvertJavaStringToUTF8(env, resource_name));
177 #else // BUILDFLAG(ENABLE_BASE_TRACING)
179 // Empty implementations when TraceLog isn't available.
180 static void JNI_TraceEvent_RegisterEnabledObserver(JNIEnv* env) {
181 base::android::Java_TraceEvent_setEnabled(env, false);
182 // This code should not be reached when base tracing is disabled. Calling
183 // setEventNameFilteringEnabled to avoid "unused function" warning.
184 base::android::Java_TraceEvent_setEventNameFilteringEnabled(env, false);
186 static jboolean JNI_TraceEvent_ViewHierarchyDumpEnabled(JNIEnv* env) {
189 static void JNI_TraceEvent_InitViewHierarchyDump(
192 const JavaParamRef<jobject>& obj) {
194 // This code should not be reached when base tracing is disabled. Calling
195 // dumpViewHierarchy to avoid "unused function" warning.
196 Java_TraceEvent_dumpViewHierarchy(env, 0, obj);
198 static jlong JNI_TraceEvent_StartActivityDump(JNIEnv* env,
199 const JavaParamRef<jstring>& name,
200 jlong dump_proto_ptr) {
203 static void JNI_TraceEvent_AddViewDump(
209 const JavaParamRef<jstring>& class_name,
210 const JavaParamRef<jstring>& resource_name,
211 jlong activity_proto_ptr) {}
213 #endif // BUILDFLAG(ENABLE_BASE_TRACING)
217 // Boilerplate for safely converting Java data to TRACE_EVENT data.
218 class TraceEventDataConverter {
220 TraceEventDataConverter(JNIEnv* env, jstring jname, jstring jarg)
221 : name_(ConvertJavaStringToUTF8(env, jname)),
222 has_arg_(jarg != nullptr),
223 arg_(jarg ? ConvertJavaStringToUTF8(env, jarg) : "") {}
225 TraceEventDataConverter(const TraceEventDataConverter&) = delete;
226 TraceEventDataConverter& operator=(const TraceEventDataConverter&) = delete;
228 ~TraceEventDataConverter() = default;
230 // Return saved values to pass to TRACE_EVENT macros.
231 const char* name() { return name_.c_str(); }
232 const char* arg_name() { return has_arg_ ? "arg" : nullptr; }
233 const std::string& arg() { return arg_; }
243 static void JNI_TraceEvent_Instant(JNIEnv* env,
244 const JavaParamRef<jstring>& jname,
245 const JavaParamRef<jstring>& jarg) {
246 TraceEventDataConverter converter(env, jname, jarg);
247 if (converter.arg_name()) {
248 TRACE_EVENT_INSTANT(internal::kJavaTraceCategory, nullptr,
249 converter.arg_name(), converter.arg(),
250 [&](::perfetto::EventContext& ctx) {
251 ctx.event()->set_name(converter.name());
254 TRACE_EVENT_INSTANT(internal::kJavaTraceCategory, nullptr,
255 [&](::perfetto::EventContext& ctx) {
256 ctx.event()->set_name(converter.name());
261 static void JNI_TraceEvent_InstantAndroidIPC(JNIEnv* env,
262 const JavaParamRef<jstring>& jname,
265 internal::kJavaTraceCategory, "AndroidIPC",
266 [&](perfetto::EventContext ctx) {
267 TraceEventDataConverter converter(env, jname, nullptr);
268 auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>();
269 auto* android_ipc = event->set_android_ipc();
270 android_ipc->set_name(converter.name());
271 android_ipc->set_dur_ms(jdur);
275 #if BUILDFLAG(ENABLE_BASE_TRACING)
277 static void JNI_TraceEvent_InstantAndroidToolbar(JNIEnv* env,
280 jint snapshot_diff) {
281 using AndroidToolbar = perfetto::protos::pbzero::AndroidToolbar;
283 internal::kJavaTraceCategory, "AndroidToolbar",
284 [&](perfetto::EventContext ctx) {
285 auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>();
286 auto* android_toolbar = event->set_android_toolbar();
287 if (block_reason >= 0) {
288 android_toolbar->set_block_capture_reason(
289 static_cast<AndroidToolbar::BlockCaptureReason>(block_reason));
291 if (allow_reason >= 0) {
292 android_toolbar->set_allow_capture_reason(
293 static_cast<AndroidToolbar::AllowCaptureReason>(allow_reason));
295 if (snapshot_diff >= 0) {
296 android_toolbar->set_snapshot_difference(
297 static_cast<AndroidToolbar::SnapshotDifference>(snapshot_diff));
302 #else // BUILDFLAG(ENABLE_BASE_TRACING)
304 // Empty implementations when TraceLog isn't available.
305 static void JNI_TraceEvent_InstantAndroidToolbar(JNIEnv* env,
308 jint snapshot_diff) {}
310 #endif // BUILDFLAG(ENABLE_BASE_TRACING)
312 static void JNI_TraceEvent_WebViewStartupTotalFactoryInit(JNIEnv* env,
315 // The following code does nothing if base tracing is disabled.
316 // TODO(b/283286049): set the track name explicitly after the Perfetto SDK
317 // migration is finished (crbug/1006541).
318 [[maybe_unused]] auto t =
319 perfetto::Track(trace_event::GetNextGlobalTraceId());
320 TRACE_EVENT_BEGIN("android_webview.timeline",
321 "WebView.Startup.CreationTime.TotalFactoryInitTime", t,
322 TimeTicks() + Milliseconds(start_time_ms));
323 TRACE_EVENT_END("android_webview.timeline", t,
324 TimeTicks() + Milliseconds(start_time_ms + duration_ms));
327 static void JNI_TraceEvent_WebViewStartupStage1(JNIEnv* env,
330 // The following code does nothing if base tracing is disabled.
331 // TODO(b/283286049): set the track name explicitly after the Perfetto SDK
332 // migration is finished (crbug/1006541).
333 [[maybe_unused]] auto t =
334 perfetto::Track(trace_event::GetNextGlobalTraceId());
335 TRACE_EVENT_BEGIN("android_webview.timeline",
336 "WebView.Startup.CreationTime.Stage1.FactoryInit", t,
337 TimeTicks() + Milliseconds(start_time_ms));
338 TRACE_EVENT_END("android_webview.timeline", t,
339 TimeTicks() + Milliseconds(start_time_ms + duration_ms));
342 static void JNI_TraceEvent_WebViewStartupStage2(JNIEnv* env,
345 jboolean is_cold_startup) {
346 // The following code does nothing if base tracing is disabled.
347 // TODO(b/283286049): set the track name explicitly after the Perfetto SDK
348 // migration is finished (crbug/1006541).
349 [[maybe_unused]] auto t =
350 perfetto::Track(trace_event::GetNextGlobalTraceId());
351 if (is_cold_startup) {
352 TRACE_EVENT_BEGIN("android_webview.timeline",
353 "WebView.Startup.CreationTime.Stage2.ProviderInit.Cold",
354 t, TimeTicks() + Milliseconds(start_time_ms));
356 TRACE_EVENT_BEGIN("android_webview.timeline",
357 "WebView.Startup.CreationTime.Stage2.ProviderInit.Warm",
358 t, TimeTicks() + Milliseconds(start_time_ms));
361 TRACE_EVENT_END("android_webview.timeline", t,
362 TimeTicks() + Milliseconds(start_time_ms + duration_ms));
365 static void JNI_TraceEvent_Begin(JNIEnv* env,
366 const JavaParamRef<jstring>& jname,
367 const JavaParamRef<jstring>& jarg) {
368 TraceEventDataConverter converter(env, jname, jarg);
369 if (converter.arg_name()) {
370 TRACE_EVENT_BEGIN(internal::kJavaTraceCategory, nullptr,
371 converter.arg_name(), converter.arg(),
372 [&](::perfetto::EventContext& ctx) {
373 ctx.event()->set_name(converter.name());
376 TRACE_EVENT_BEGIN(internal::kJavaTraceCategory, nullptr,
377 [&](::perfetto::EventContext& ctx) {
378 ctx.event()->set_name(converter.name());
383 static void JNI_TraceEvent_BeginWithIntArg(JNIEnv* env,
384 const JavaParamRef<jstring>& jname,
386 TraceEventDataConverter converter(env, jname, nullptr);
387 TRACE_EVENT_BEGIN(internal::kJavaTraceCategory, nullptr, "arg", jarg,
388 [&](::perfetto::EventContext& ctx) {
389 ctx.event()->set_name(converter.name());
393 static void JNI_TraceEvent_End(JNIEnv* env,
394 const JavaParamRef<jstring>& jname,
395 const JavaParamRef<jstring>& jarg,
397 TraceEventDataConverter converter(env, jname, jarg);
398 bool has_arg = converter.arg_name();
399 bool has_flow = jflow != 0;
400 if (has_arg && has_flow) {
401 TRACE_EVENT_END(internal::kJavaTraceCategory,
402 perfetto::Flow::ProcessScoped(static_cast<uint64_t>(jflow)),
403 converter.arg_name(), converter.arg());
404 } else if (has_arg) {
405 TRACE_EVENT_END(internal::kJavaTraceCategory, converter.arg_name(),
407 } else if (has_flow) {
409 internal::kJavaTraceCategory,
410 perfetto::Flow::ProcessScoped(static_cast<uint64_t>(jflow)));
412 TRACE_EVENT_END(internal::kJavaTraceCategory);
416 static void JNI_TraceEvent_BeginToplevel(JNIEnv* env,
417 const JavaParamRef<jstring>& jtarget) {
418 std::string target = ConvertJavaStringToUTF8(env, jtarget);
419 TRACE_EVENT_BEGIN(internal::kToplevelTraceCategory, nullptr,
420 [&](::perfetto::EventContext& ctx) {
421 ctx.event()->set_name(target.c_str());
425 static void JNI_TraceEvent_EndToplevel(JNIEnv* env,
426 const JavaParamRef<jstring>& jtarget) {
427 std::string target = ConvertJavaStringToUTF8(env, jtarget);
428 TRACE_EVENT_END(internal::kToplevelTraceCategory);
431 static void JNI_TraceEvent_StartAsync(JNIEnv* env,
432 const JavaParamRef<jstring>& jname,
434 TraceEventDataConverter converter(env, jname, nullptr);
435 TRACE_EVENT_BEGIN(internal::kJavaTraceCategory, nullptr,
436 perfetto::Track(static_cast<uint64_t>(jid)),
437 [&](::perfetto::EventContext& ctx) {
438 ctx.event()->set_name(converter.name());
442 static void JNI_TraceEvent_FinishAsync(JNIEnv* env,
443 const JavaParamRef<jstring>& jname,
445 TraceEventDataConverter converter(env, jname, nullptr);
446 TRACE_EVENT_END(internal::kJavaTraceCategory,
447 perfetto::Track(static_cast<uint64_t>(jid)));
450 } // namespace android