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.
4
5 #include <jni.h>
6
7 #include <set>
8
9 #include "base/android/jni_string.h"
10 #include "base/android/trace_event_binding.h"
11 #include "base/metrics/histogram_macros.h"
12 #include "base/trace_event/base_tracing.h"
13 #include "base/tracing_buildflags.h"
14 #include "build/robolectric_buildflags.h"
15
16 #if BUILDFLAG(IS_ROBOLECTRIC)
17 #include "base/base_robolectric_jni/TraceEvent_jni.h" // nogncheck
18 #else
19 #include "base/base_jni/TraceEvent_jni.h"
20 #endif
21
22 #if BUILDFLAG(ENABLE_BASE_TRACING)
23 #include "base/trace_event/trace_event_impl.h" // no-presubmit-check
24 #include "third_party/perfetto/include/perfetto/tracing/track.h" // no-presubmit-check nogncheck
25 #include "third_party/perfetto/protos/perfetto/config/chrome/chrome_config.gen.h" // nogncheck
26 #endif // BUILDFLAG(ENABLE_BASE_TRACING)
27
28 namespace base {
29 namespace android {
30
31 #if BUILDFLAG(ENABLE_BASE_TRACING)
32
33 namespace {
34
35 constexpr const char kAndroidViewHierarchyTraceCategory[] =
36 TRACE_DISABLED_BY_DEFAULT("android_view_hierarchy");
37 constexpr const char kAndroidViewHierarchyEventName[] = "AndroidView";
38
39 #if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
40 class TraceEnabledObserver : public perfetto::TrackEventSessionObserver {
41 public:
GetInstance()42 static TraceEnabledObserver* GetInstance() {
43 static base::NoDestructor<TraceEnabledObserver> instance;
44 return instance.get();
45 }
46
47 // perfetto::TrackEventSessionObserver implementation
OnSetup(const perfetto::DataSourceBase::SetupArgs & args)48 void OnSetup(const perfetto::DataSourceBase::SetupArgs& args) override {
49 trace_event::TraceConfig trace_config(
50 args.config->chrome_config().trace_config());
51 event_name_filtering_per_session_[args.internal_instance_index] =
52 trace_config.IsEventPackageNameFilterEnabled();
53 }
54
OnStart(const perfetto::DataSourceBase::StartArgs &)55 void OnStart(const perfetto::DataSourceBase::StartArgs&) override {
56 JNIEnv* env = jni_zero::AttachCurrentThread();
57 base::android::Java_TraceEvent_setEnabled(env, true);
58 base::android::Java_TraceEvent_setEventNameFilteringEnabled(
59 env, EventNameFilteringEnabled());
60 }
61
OnStop(const perfetto::DataSourceBase::StopArgs & args)62 void OnStop(const perfetto::DataSourceBase::StopArgs& args) override {
63 event_name_filtering_per_session_.erase(args.internal_instance_index);
64
65 JNIEnv* env = jni_zero::AttachCurrentThread();
66 base::android::Java_TraceEvent_setEnabled(
67 env, !event_name_filtering_per_session_.empty());
68 base::android::Java_TraceEvent_setEventNameFilteringEnabled(
69 env, EventNameFilteringEnabled());
70 }
71
72 private:
73 friend class base::NoDestructor<TraceEnabledObserver>;
74 TraceEnabledObserver() = default;
75 ~TraceEnabledObserver() override = default;
76
77 // Return true if event name filtering is requested by at least one tracing
78 // session.
EventNameFilteringEnabled() const79 bool EventNameFilteringEnabled() const {
80 bool event_name_filtering_enabled = false;
81 for (const auto& entry : event_name_filtering_per_session_) {
82 if (entry.second) {
83 event_name_filtering_enabled = true;
84 }
85 }
86 return event_name_filtering_enabled;
87 }
88
89 std::unordered_map<uint32_t, bool> event_name_filtering_per_session_;
90 };
91
92 #else // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
93
94 class TraceEnabledObserver
95 : public trace_event::TraceLog::EnabledStateObserver {
96 public:
97 ~TraceEnabledObserver() override = default;
98
99 // trace_event::TraceLog::EnabledStateObserver:
OnTraceLogEnabled()100 void OnTraceLogEnabled() override {
101 JNIEnv* env = jni_zero::AttachCurrentThread();
102 base::android::Java_TraceEvent_setEnabled(env, true);
103 if (base::trace_event::TraceLog::GetInstance()
104 ->GetCurrentTraceConfig()
105 .IsEventPackageNameFilterEnabled()) {
106 base::android::Java_TraceEvent_setEventNameFilteringEnabled(env, true);
107 }
108 }
109
OnTraceLogDisabled()110 void OnTraceLogDisabled() override {
111 JNIEnv* env = jni_zero::AttachCurrentThread();
112 base::android::Java_TraceEvent_setEnabled(env, false);
113 base::android::Java_TraceEvent_setEventNameFilteringEnabled(env, false);
114 }
115 };
116 #endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
117
118 } // namespace
119
JNI_TraceEvent_RegisterEnabledObserver(JNIEnv * env)120 static void JNI_TraceEvent_RegisterEnabledObserver(JNIEnv* env) {
121 #if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
122 base::android::Java_TraceEvent_setEnabled(env, base::TrackEvent::IsEnabled());
123 base::TrackEvent::AddSessionObserver(TraceEnabledObserver::GetInstance());
124 #else
125 bool enabled = trace_event::TraceLog::GetInstance()->IsEnabled();
126 base::android::Java_TraceEvent_setEnabled(env, enabled);
127 trace_event::TraceLog::GetInstance()->AddOwnedEnabledStateObserver(
128 std::make_unique<TraceEnabledObserver>());
129 #endif
130 }
131
JNI_TraceEvent_ViewHierarchyDumpEnabled(JNIEnv * env)132 static jboolean JNI_TraceEvent_ViewHierarchyDumpEnabled(JNIEnv* env) {
133 static const unsigned char* enabled =
134 TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
135 kAndroidViewHierarchyTraceCategory);
136 return *enabled;
137 }
138
JNI_TraceEvent_InitViewHierarchyDump(JNIEnv * env,jlong id,const JavaParamRef<jobject> & obj)139 static void JNI_TraceEvent_InitViewHierarchyDump(
140 JNIEnv* env,
141 jlong id,
142 const JavaParamRef<jobject>& obj) {
143 TRACE_EVENT(
144 kAndroidViewHierarchyTraceCategory, kAndroidViewHierarchyEventName,
145 perfetto::TerminatingFlow::ProcessScoped(static_cast<uint64_t>(id)),
146 [&](perfetto::EventContext ctx) {
147 auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>();
148 auto* dump = event->set_android_view_dump();
149 Java_TraceEvent_dumpViewHierarchy(env, reinterpret_cast<jlong>(dump),
150 obj);
151 });
152 }
153
JNI_TraceEvent_StartActivityDump(JNIEnv * env,const JavaParamRef<jstring> & name,jlong dump_proto_ptr)154 static jlong JNI_TraceEvent_StartActivityDump(JNIEnv* env,
155 const JavaParamRef<jstring>& name,
156 jlong dump_proto_ptr) {
157 auto* dump = reinterpret_cast<perfetto::protos::pbzero::AndroidViewDump*>(
158 dump_proto_ptr);
159 auto* activity = dump->add_activity();
160 activity->set_name(ConvertJavaStringToUTF8(env, name));
161 return reinterpret_cast<jlong>(activity);
162 }
163
JNI_TraceEvent_AddViewDump(JNIEnv * env,jint id,jint parent_id,jboolean is_shown,jboolean is_dirty,const JavaParamRef<jstring> & class_name,const JavaParamRef<jstring> & resource_name,jlong activity_proto_ptr)164 static void JNI_TraceEvent_AddViewDump(
165 JNIEnv* env,
166 jint id,
167 jint parent_id,
168 jboolean is_shown,
169 jboolean is_dirty,
170 const JavaParamRef<jstring>& class_name,
171 const JavaParamRef<jstring>& resource_name,
172 jlong activity_proto_ptr) {
173 auto* activity = reinterpret_cast<perfetto::protos::pbzero::AndroidActivity*>(
174 activity_proto_ptr);
175 auto* view = activity->add_view();
176 view->set_id(id);
177 view->set_parent_id(parent_id);
178 view->set_is_shown(is_shown);
179 view->set_is_dirty(is_dirty);
180 view->set_class_name(ConvertJavaStringToUTF8(env, class_name));
181 view->set_resource_name(ConvertJavaStringToUTF8(env, resource_name));
182 }
183
184 #else // BUILDFLAG(ENABLE_BASE_TRACING)
185
186 // Empty implementations when TraceLog isn't available.
187 static void JNI_TraceEvent_RegisterEnabledObserver(JNIEnv* env) {
188 base::android::Java_TraceEvent_setEnabled(env, false);
189 // This code should not be reached when base tracing is disabled. Calling
190 // setEventNameFilteringEnabled to avoid "unused function" warning.
191 base::android::Java_TraceEvent_setEventNameFilteringEnabled(env, false);
192 }
193 static jboolean JNI_TraceEvent_ViewHierarchyDumpEnabled(JNIEnv* env) {
194 return false;
195 }
196 static void JNI_TraceEvent_InitViewHierarchyDump(
197 JNIEnv* env,
198 jlong id,
199 const JavaParamRef<jobject>& obj) {
200 DCHECK(false);
201 // This code should not be reached when base tracing is disabled. Calling
202 // dumpViewHierarchy to avoid "unused function" warning.
203 Java_TraceEvent_dumpViewHierarchy(env, 0, obj);
204 }
205 static jlong JNI_TraceEvent_StartActivityDump(JNIEnv* env,
206 const JavaParamRef<jstring>& name,
207 jlong dump_proto_ptr) {
208 return 0;
209 }
210 static void JNI_TraceEvent_AddViewDump(
211 JNIEnv* env,
212 jint id,
213 jint parent_id,
214 jboolean is_shown,
215 jboolean is_dirty,
216 const JavaParamRef<jstring>& class_name,
217 const JavaParamRef<jstring>& resource_name,
218 jlong activity_proto_ptr) {}
219
220 #endif // BUILDFLAG(ENABLE_BASE_TRACING)
221
222 namespace {
223
224 // Boilerplate for safely converting Java data to TRACE_EVENT data.
225 class TraceEventDataConverter {
226 public:
TraceEventDataConverter(JNIEnv * env,jstring jarg)227 TraceEventDataConverter(JNIEnv* env, jstring jarg)
228 : has_arg_(jarg != nullptr),
229 arg_(jarg ? ConvertJavaStringToUTF8(env, jarg) : "") {}
230
231 TraceEventDataConverter(const TraceEventDataConverter&) = delete;
232 TraceEventDataConverter& operator=(const TraceEventDataConverter&) = delete;
233
234 ~TraceEventDataConverter() = default;
235
236 // Return saved values to pass to TRACE_EVENT macros.
arg_name()237 const char* arg_name() { return has_arg_ ? "arg" : nullptr; }
arg()238 const std::string& arg() { return arg_; }
239
240 private:
241 bool has_arg_;
242 std::string arg_;
243 };
244
245 } // namespace
246
JNI_TraceEvent_Instant(JNIEnv * env,const JavaParamRef<jstring> & jname,const JavaParamRef<jstring> & jarg)247 static void JNI_TraceEvent_Instant(JNIEnv* env,
248 const JavaParamRef<jstring>& jname,
249 const JavaParamRef<jstring>& jarg) {
250 TraceEventDataConverter converter(env, jarg);
251
252 if (converter.arg_name()) {
253 TRACE_EVENT_INSTANT(
254 internal::kJavaTraceCategory, nullptr, converter.arg_name(),
255 converter.arg(), [&](::perfetto::EventContext& ctx) {
256 ctx.event()->set_name(ConvertJavaStringToUTF8(env, jname));
257 });
258 } else {
259 TRACE_EVENT_INSTANT(
260 internal::kJavaTraceCategory, nullptr,
261 [&](::perfetto::EventContext& ctx) {
262 ctx.event()->set_name(ConvertJavaStringToUTF8(env, jname));
263 });
264 }
265 }
266
JNI_TraceEvent_InstantAndroidIPC(JNIEnv * env,const JavaParamRef<jstring> & jname,jlong jdur)267 static void JNI_TraceEvent_InstantAndroidIPC(JNIEnv* env,
268 const JavaParamRef<jstring>& jname,
269 jlong jdur) {
270 TRACE_EVENT_INSTANT(
271 internal::kJavaTraceCategory, "AndroidIPC",
272 [&](perfetto::EventContext ctx) {
273 auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>();
274 auto* android_ipc = event->set_android_ipc();
275 android_ipc->set_name(ConvertJavaStringToUTF8(env, jname));
276 android_ipc->set_dur_ms(jdur);
277 });
278 }
279
280 #if BUILDFLAG(ENABLE_BASE_TRACING)
281
JNI_TraceEvent_InstantAndroidToolbar(JNIEnv * env,jint block_reason,jint allow_reason,jint snapshot_diff)282 static void JNI_TraceEvent_InstantAndroidToolbar(JNIEnv* env,
283 jint block_reason,
284 jint allow_reason,
285 jint snapshot_diff) {
286 using AndroidToolbar = perfetto::protos::pbzero::AndroidToolbar;
287 TRACE_EVENT_INSTANT(
288 internal::kJavaTraceCategory, "AndroidToolbar",
289 [&](perfetto::EventContext ctx) {
290 auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>();
291 auto* android_toolbar = event->set_android_toolbar();
292 if (block_reason >= 0) {
293 android_toolbar->set_block_capture_reason(
294 static_cast<AndroidToolbar::BlockCaptureReason>(block_reason));
295 }
296 if (allow_reason >= 0) {
297 android_toolbar->set_allow_capture_reason(
298 static_cast<AndroidToolbar::AllowCaptureReason>(allow_reason));
299 }
300 if (snapshot_diff >= 0) {
301 android_toolbar->set_snapshot_difference(
302 static_cast<AndroidToolbar::SnapshotDifference>(snapshot_diff));
303 }
304 });
305 }
306
307 #else // BUILDFLAG(ENABLE_BASE_TRACING)
308
309 // Empty implementations when TraceLog isn't available.
JNI_TraceEvent_InstantAndroidToolbar(JNIEnv * env,jint block_reason,jint allow_reason,jint snapshot_diff)310 static void JNI_TraceEvent_InstantAndroidToolbar(JNIEnv* env,
311 jint block_reason,
312 jint allow_reason,
313 jint snapshot_diff) {}
314
315 #endif // BUILDFLAG(ENABLE_BASE_TRACING)
316
JNI_TraceEvent_WebViewStartupTotalFactoryInit(JNIEnv * env,jlong start_time_ms,jlong duration_ms)317 static void JNI_TraceEvent_WebViewStartupTotalFactoryInit(JNIEnv* env,
318 jlong start_time_ms,
319 jlong duration_ms) {
320 #if BUILDFLAG(ENABLE_BASE_TRACING)
321 auto t = perfetto::Track::ThreadScoped(env);
322 auto desc = t.Serialize();
323 desc.set_name("android_webview.timeline");
324 TRACE_EVENT_BEGIN("android_webview.timeline",
325 "WebView.Startup.CreationTime.TotalFactoryInitTime", t,
326 TimeTicks() + Milliseconds(start_time_ms));
327 TRACE_EVENT_END("android_webview.timeline", t,
328 TimeTicks() + Milliseconds(start_time_ms + duration_ms));
329 #endif // BUILDFLAG(ENABLE_BASE_TRACING)
330 }
331
JNI_TraceEvent_WebViewStartupStage1(JNIEnv * env,jlong start_time_ms,jlong duration_ms)332 static void JNI_TraceEvent_WebViewStartupStage1(JNIEnv* env,
333 jlong start_time_ms,
334 jlong duration_ms) {
335 #if BUILDFLAG(ENABLE_BASE_TRACING)
336 auto t = perfetto::Track::ThreadScoped(env);
337 auto desc = t.Serialize();
338 desc.set_name("android_webview.timeline");
339 TRACE_EVENT_BEGIN("android_webview.timeline",
340 "WebView.Startup.CreationTime.Stage1.FactoryInit", t,
341 TimeTicks() + Milliseconds(start_time_ms));
342 TRACE_EVENT_END("android_webview.timeline", t,
343 TimeTicks() + Milliseconds(start_time_ms + duration_ms));
344 #endif // BUILDFLAG(ENABLE_BASE_TRACING)
345 }
346
JNI_TraceEvent_WebViewStartupStage2(JNIEnv * env,jlong start_time_ms,jlong duration_ms,jboolean is_cold_startup)347 static void JNI_TraceEvent_WebViewStartupStage2(JNIEnv* env,
348 jlong start_time_ms,
349 jlong duration_ms,
350 jboolean is_cold_startup) {
351 #if BUILDFLAG(ENABLE_BASE_TRACING)
352 auto t = perfetto::Track::ThreadScoped(env);
353 auto desc = t.Serialize();
354 desc.set_name("android_webview.timeline");
355 if (is_cold_startup) {
356 TRACE_EVENT_BEGIN("android_webview.timeline",
357 "WebView.Startup.CreationTime.Stage2.ProviderInit.Cold",
358 t, TimeTicks() + Milliseconds(start_time_ms));
359 } else {
360 TRACE_EVENT_BEGIN("android_webview.timeline",
361 "WebView.Startup.CreationTime.Stage2.ProviderInit.Warm",
362 t, TimeTicks() + Milliseconds(start_time_ms));
363 }
364
365 TRACE_EVENT_END("android_webview.timeline", t,
366 TimeTicks() + Milliseconds(start_time_ms + duration_ms));
367 #endif // BUILDFLAG(ENABLE_BASE_TRACING)
368 }
369
JNI_TraceEvent_WebViewStartupStartChromiumLocked(JNIEnv * env,jlong start_time_ms,jlong duration_ms)370 static void JNI_TraceEvent_WebViewStartupStartChromiumLocked(
371 JNIEnv* env,
372 jlong start_time_ms,
373 jlong duration_ms) {
374 #if BUILDFLAG(ENABLE_BASE_TRACING)
375 auto t = perfetto::Track::ThreadScoped(env);
376 auto desc = t.Serialize();
377 desc.set_name("android_webview.timeline");
378 TrackEvent::SetTrackDescriptor(t, desc);
379 TRACE_EVENT_BEGIN("android_webview.timeline",
380 "WebView.Startup.CreationTime.StartChromiumLocked", t,
381 TimeTicks() + Milliseconds(start_time_ms));
382 TRACE_EVENT_END("android_webview.timeline", t,
383 TimeTicks() + Milliseconds(start_time_ms + duration_ms));
384 #endif // BUILDFLAG(ENABLE_BASE_TRACING)
385 }
386
JNI_TraceEvent_StartupActivityStart(JNIEnv * env,jlong activity_id,jlong start_time_ms)387 static void JNI_TraceEvent_StartupActivityStart(JNIEnv* env,
388 jlong activity_id,
389 jlong start_time_ms) {
390 TRACE_EVENT_INSTANT(
391 "interactions", "Startup.ActivityStart",
392 TimeTicks() + Milliseconds(start_time_ms),
393 [&](perfetto::EventContext ctx) {
394 auto* start_up = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>()
395 ->set_startup();
396 start_up->set_activity_id(activity_id);
397 });
398 }
399
JNI_TraceEvent_StartupLaunchCause(JNIEnv * env,jlong activity_id,jlong start_time_ms,jint cause)400 static void JNI_TraceEvent_StartupLaunchCause(JNIEnv* env,
401 jlong activity_id,
402 jlong start_time_ms,
403 jint cause) {
404 #if BUILDFLAG(ENABLE_BASE_TRACING)
405 using Startup = perfetto::protos::pbzero::StartUp;
406 auto launchType = Startup::OTHER;
407 switch (cause) {
408 case Startup::CUSTOM_TAB:
409 launchType = Startup::CUSTOM_TAB;
410 break;
411 case Startup::TWA:
412 launchType = Startup::TWA;
413 break;
414 case Startup::RECENTS:
415 launchType = Startup::RECENTS;
416 break;
417 case Startup::RECENTS_OR_BACK:
418 launchType = Startup::RECENTS_OR_BACK;
419 break;
420 case Startup::FOREGROUND_WHEN_LOCKED:
421 launchType = Startup::FOREGROUND_WHEN_LOCKED;
422 break;
423 case Startup::MAIN_LAUNCHER_ICON:
424 launchType = Startup::MAIN_LAUNCHER_ICON;
425 break;
426 case Startup::MAIN_LAUNCHER_ICON_SHORTCUT:
427 launchType = Startup::MAIN_LAUNCHER_ICON_SHORTCUT;
428 break;
429 case Startup::HOME_SCREEN_WIDGET:
430 launchType = Startup::HOME_SCREEN_WIDGET;
431 break;
432 case Startup::OPEN_IN_BROWSER_FROM_MENU:
433 launchType = Startup::OPEN_IN_BROWSER_FROM_MENU;
434 break;
435 case Startup::EXTERNAL_SEARCH_ACTION_INTENT:
436 launchType = Startup::EXTERNAL_SEARCH_ACTION_INTENT;
437 break;
438 case Startup::NOTIFICATION:
439 launchType = Startup::NOTIFICATION;
440 break;
441 case Startup::EXTERNAL_VIEW_INTENT:
442 launchType = Startup::EXTERNAL_VIEW_INTENT;
443 break;
444 case Startup::OTHER_CHROME:
445 launchType = Startup::OTHER_CHROME;
446 break;
447 case Startup::WEBAPK_CHROME_DISTRIBUTOR:
448 launchType = Startup::WEBAPK_CHROME_DISTRIBUTOR;
449 break;
450 case Startup::WEBAPK_OTHER_DISTRIBUTOR:
451 launchType = Startup::WEBAPK_OTHER_DISTRIBUTOR;
452 break;
453 case Startup::HOME_SCREEN_SHORTCUT:
454 launchType = Startup::HOME_SCREEN_SHORTCUT;
455 break;
456 case Startup::SHARE_INTENT:
457 launchType = Startup::SHARE_INTENT;
458 break;
459 case Startup::NFC:
460 launchType = Startup::NFC;
461 break;
462 default:
463 break;
464 }
465
466 TRACE_EVENT_INSTANT(
467 "interactions,startup", "Startup.LaunchCause",
468 TimeTicks() + Milliseconds(start_time_ms),
469 [&](perfetto::EventContext ctx) {
470 auto* start_up = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>()
471 ->set_startup();
472 start_up->set_activity_id(activity_id);
473 start_up->set_launch_cause(launchType);
474 });
475 #endif // BUILDFLAG(ENABLE_BASE_TRACING)
476 }
477
JNI_TraceEvent_StartupTimeToFirstVisibleContent2(JNIEnv * env,jlong activity_id,jlong start_time_ms,jlong duration_ms)478 static void JNI_TraceEvent_StartupTimeToFirstVisibleContent2(
479 JNIEnv* env,
480 jlong activity_id,
481 jlong start_time_ms,
482 jlong duration_ms) {
483 #if BUILDFLAG(ENABLE_BASE_TRACING)
484 [[maybe_unused]] const perfetto::Track track(
485 base::trace_event::GetNextGlobalTraceId(),
486 perfetto::ProcessTrack::Current());
487 TRACE_EVENT_BEGIN(
488 "interactions,startup", "Startup.TimeToFirstVisibleContent2", track,
489 TimeTicks() + Milliseconds(start_time_ms),
490 [&](perfetto::EventContext ctx) {
491 auto* start_up = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>()
492 ->set_startup();
493 start_up->set_activity_id(activity_id);
494 });
495
496 TRACE_EVENT_END("interactions,startup", track,
497 TimeTicks() + Milliseconds(start_time_ms + duration_ms));
498 #endif // BUILDFLAG(ENABLE_BASE_TRACING)
499 }
500
JNI_TraceEvent_Begin(JNIEnv * env,const JavaParamRef<jstring> & jname,const JavaParamRef<jstring> & jarg)501 static void JNI_TraceEvent_Begin(JNIEnv* env,
502 const JavaParamRef<jstring>& jname,
503 const JavaParamRef<jstring>& jarg) {
504 TraceEventDataConverter converter(env, jarg);
505 if (converter.arg_name()) {
506 TRACE_EVENT_BEGIN(
507 internal::kJavaTraceCategory, nullptr, converter.arg_name(),
508 converter.arg(), [&](::perfetto::EventContext& ctx) {
509 ctx.event()->set_name(ConvertJavaStringToUTF8(env, jname));
510 });
511 } else {
512 TRACE_EVENT_BEGIN(
513 internal::kJavaTraceCategory, nullptr,
514 [&](::perfetto::EventContext& ctx) {
515 ctx.event()->set_name(ConvertJavaStringToUTF8(env, jname));
516 });
517 }
518 }
519
JNI_TraceEvent_BeginWithIntArg(JNIEnv * env,const JavaParamRef<jstring> & jname,jint jarg)520 static void JNI_TraceEvent_BeginWithIntArg(JNIEnv* env,
521 const JavaParamRef<jstring>& jname,
522 jint jarg) {
523 TRACE_EVENT_BEGIN(
524 internal::kJavaTraceCategory, nullptr, "arg", jarg,
525 [&](::perfetto::EventContext& ctx) {
526 ctx.event()->set_name(ConvertJavaStringToUTF8(env, jname));
527 });
528 }
529
JNI_TraceEvent_End(JNIEnv * env,const JavaParamRef<jstring> & jarg,jlong jflow)530 static void JNI_TraceEvent_End(JNIEnv* env,
531 const JavaParamRef<jstring>& jarg,
532 jlong jflow) {
533 TraceEventDataConverter converter(env, jarg);
534 bool has_arg = converter.arg_name();
535 bool has_flow = jflow != 0;
536 if (has_arg && has_flow) {
537 TRACE_EVENT_END(internal::kJavaTraceCategory,
538 perfetto::Flow::ProcessScoped(static_cast<uint64_t>(jflow)),
539 converter.arg_name(), converter.arg());
540 } else if (has_arg) {
541 TRACE_EVENT_END(internal::kJavaTraceCategory, converter.arg_name(),
542 converter.arg());
543 } else if (has_flow) {
544 TRACE_EVENT_END(
545 internal::kJavaTraceCategory,
546 perfetto::Flow::ProcessScoped(static_cast<uint64_t>(jflow)));
547 } else {
548 TRACE_EVENT_END(internal::kJavaTraceCategory);
549 }
550 }
551
JNI_TraceEvent_BeginToplevel(JNIEnv * env,const JavaParamRef<jstring> & jtarget)552 static void JNI_TraceEvent_BeginToplevel(JNIEnv* env,
553 const JavaParamRef<jstring>& jtarget) {
554 TRACE_EVENT_BEGIN(
555 internal::kToplevelTraceCategory, nullptr,
556 [&](::perfetto::EventContext& ctx) {
557 ctx.event()->set_name(ConvertJavaStringToUTF8(env, jtarget));
558 });
559 }
560
JNI_TraceEvent_EndToplevel(JNIEnv * env)561 static void JNI_TraceEvent_EndToplevel(JNIEnv* env) {
562 TRACE_EVENT_END(internal::kToplevelTraceCategory);
563 }
564
JNI_TraceEvent_StartAsync(JNIEnv * env,const JavaParamRef<jstring> & jname,jlong jid)565 static void JNI_TraceEvent_StartAsync(JNIEnv* env,
566 const JavaParamRef<jstring>& jname,
567 jlong jid) {
568 TRACE_EVENT_BEGIN(
569 internal::kJavaTraceCategory, nullptr,
570 perfetto::Track(static_cast<uint64_t>(jid)),
571 [&](::perfetto::EventContext& ctx) {
572 ctx.event()->set_name(ConvertJavaStringToUTF8(env, jname));
573 });
574 }
575
JNI_TraceEvent_FinishAsync(JNIEnv * env,jlong jid)576 static void JNI_TraceEvent_FinishAsync(JNIEnv* env,
577 jlong jid) {
578 TRACE_EVENT_END(internal::kJavaTraceCategory,
579 perfetto::Track(static_cast<uint64_t>(jid)));
580 }
581
582 } // namespace android
583 } // namespace base
584