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