• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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