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