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