1 // Copyright 2013 The Flutter Authors. All rights reserved.
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 "flutter/shell/common/skia_event_tracer_impl.h"
6
7 #define TRACE_EVENT_HIDE_MACROS
8 #include <vector>
9
10 #include "flutter/fml/logging.h"
11 #include "flutter/fml/trace_event.h"
12 #include "third_party/skia/include/utils/SkEventTracer.h"
13 #include "third_party/skia/include/utils/SkTraceEventPhase.h"
14
15 namespace flutter {
16
17 class FlutterEventTracer : public SkEventTracer {
18 public:
19 static constexpr const char* kSkiaTag = "skia";
20 static constexpr uint8_t kYes = 1;
21 static constexpr uint8_t kNo = 0;
22
FlutterEventTracer(bool enabled)23 FlutterEventTracer(bool enabled) : enabled_(enabled ? kYes : kNo){};
24
addTraceEvent(char phase,const uint8_t * category_enabled_flag,const char * name,uint64_t id,int num_args,const char ** p_arg_names,const uint8_t * p_arg_types,const uint64_t * p_arg_values,uint8_t flags)25 SkEventTracer::Handle addTraceEvent(char phase,
26 const uint8_t* category_enabled_flag,
27 const char* name,
28 uint64_t id,
29 int num_args,
30 const char** p_arg_names,
31 const uint8_t* p_arg_types,
32 const uint64_t* p_arg_values,
33 uint8_t flags) override {
34 #if defined(OS_FUCHSIA)
35 // In a manner analogous to "fml/trace_event.h", use Fuchsia's system
36 // tracing macros when running on Fuchsia.
37 switch (phase) {
38 case TRACE_EVENT_PHASE_BEGIN:
39 case TRACE_EVENT_PHASE_COMPLETE:
40 TRACE_DURATION_BEGIN(kSkiaTag, name);
41 break;
42 case TRACE_EVENT_PHASE_END:
43 TRACE_DURATION_END(kSkiaTag, name);
44 break;
45 case TRACE_EVENT_PHASE_INSTANT:
46 TRACE_INSTANT(kSkiaTag, name, TRACE_SCOPE_THREAD);
47 break;
48 case TRACE_EVENT_PHASE_ASYNC_BEGIN:
49 TRACE_ASYNC_BEGIN(kSkiaTag, name, id);
50 break;
51 case TRACE_EVENT_PHASE_ASYNC_END:
52 TRACE_ASYNC_END(kSkiaTag, name, id);
53 break;
54 default:
55 break;
56 }
57 #else // defined(OS_FUCHSIA)
58 switch (phase) {
59 case TRACE_EVENT_PHASE_BEGIN:
60 case TRACE_EVENT_PHASE_COMPLETE:
61 fml::tracing::TraceEvent0(kSkiaTag, name);
62 break;
63 case TRACE_EVENT_PHASE_END:
64 fml::tracing::TraceEventEnd(name);
65 break;
66 case TRACE_EVENT_PHASE_INSTANT:
67 fml::tracing::TraceEventInstant0(kSkiaTag, name);
68 break;
69 case TRACE_EVENT_PHASE_ASYNC_BEGIN:
70 fml::tracing::TraceEventAsyncBegin0(kSkiaTag, name, id);
71 break;
72 case TRACE_EVENT_PHASE_ASYNC_END:
73 fml::tracing::TraceEventAsyncEnd0(kSkiaTag, name, id);
74 break;
75 default:
76 break;
77 }
78 #endif // defined(OS_FUCHSIA)
79 return 0;
80 }
81
updateTraceEventDuration(const uint8_t * category_enabled_flag,const char * name,SkEventTracer::Handle handle)82 void updateTraceEventDuration(const uint8_t* category_enabled_flag,
83 const char* name,
84 SkEventTracer::Handle handle) override {
85 // This is only ever called from a scoped trace event so we will just end
86 // the section.
87 #if defined(OS_FUCHSIA)
88 TRACE_DURATION_END(kSkiaTag, name);
89 #else
90 fml::tracing::TraceEventEnd(name);
91 #endif
92 }
93
getCategoryGroupEnabled(const char * name)94 const uint8_t* getCategoryGroupEnabled(const char* name) override {
95 return &enabled_;
96 }
97
getCategoryGroupName(const uint8_t * category_enabled_flag)98 const char* getCategoryGroupName(
99 const uint8_t* category_enabled_flag) override {
100 return kSkiaTag;
101 }
102
enable()103 void enable() { enabled_ = kYes; }
104
105 private:
106 uint8_t enabled_;
107 FML_DISALLOW_COPY_AND_ASSIGN(FlutterEventTracer);
108 };
109
enableSkiaTracingCallback(const char * method,const char ** param_keys,const char ** param_values,intptr_t num_params,void * user_data,const char ** json_object)110 bool enableSkiaTracingCallback(const char* method,
111 const char** param_keys,
112 const char** param_values,
113 intptr_t num_params,
114 void* user_data,
115 const char** json_object) {
116 FlutterEventTracer* tracer = static_cast<FlutterEventTracer*>(user_data);
117 tracer->enable();
118 *json_object = strdup("{\"type\":\"Success\"}");
119 return true;
120 }
121
InitSkiaEventTracer(bool enabled)122 void InitSkiaEventTracer(bool enabled) {
123 // TODO(chinmaygarde): Leaked https://github.com/flutter/flutter/issues/30808.
124 auto tracer = new FlutterEventTracer(enabled);
125 Dart_RegisterRootServiceRequestCallback("_flutter.enableSkiaTracing",
126 enableSkiaTracingCallback,
127 static_cast<void*>(tracer));
128 // Initialize the binding to Skia's tracing events. Skia will
129 // take ownership of and clean up the memory allocated here.
130 SkEventTracer::SetInstance(tracer);
131 }
132
133 } // namespace flutter
134