• 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 <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