1 // Copyright 2014 The Chromium 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 <jni.h>
6
7 #include <set>
8
9 #include "base/android/jni_string.h"
10 #include "base/lazy_instance.h"
11 #include "base/macros.h"
12 #include "base/trace_event/trace_event.h"
13 #include "base/trace_event/trace_event_impl.h"
14 #include "jni/TraceEvent_jni.h"
15
16 namespace base {
17 namespace android {
18
19 namespace {
20
21 const char kJavaCategory[] = "Java";
22 const char kToplevelCategory[] = "toplevel";
23 const char kLooperDispatchMessage[] = "Looper.dispatchMessage";
24
25 // Boilerplate for safely converting Java data to TRACE_EVENT data.
26 class TraceEventDataConverter {
27 public:
TraceEventDataConverter(JNIEnv * env,jstring jname,jstring jarg)28 TraceEventDataConverter(JNIEnv* env, jstring jname, jstring jarg)
29 : name_(ConvertJavaStringToUTF8(env, jname)),
30 has_arg_(jarg != nullptr),
31 arg_(jarg ? ConvertJavaStringToUTF8(env, jarg) : "") {}
~TraceEventDataConverter()32 ~TraceEventDataConverter() {
33 }
34
35 // Return saves values to pass to TRACE_EVENT macros.
name()36 const char* name() { return name_.c_str(); }
arg_name()37 const char* arg_name() { return has_arg_ ? "arg" : nullptr; }
arg()38 const char* arg() { return has_arg_ ? arg_.c_str() : nullptr; }
39
40 private:
41 std::string name_;
42 bool has_arg_;
43 std::string arg_;
44
45 DISALLOW_COPY_AND_ASSIGN(TraceEventDataConverter);
46 };
47
48 class TraceEnabledObserver
49 : public trace_event::TraceLog::EnabledStateObserver {
50 public:
OnTraceLogEnabled()51 void OnTraceLogEnabled() override {
52 JNIEnv* env = base::android::AttachCurrentThread();
53 base::android::Java_TraceEvent_setEnabled(env, true);
54 }
OnTraceLogDisabled()55 void OnTraceLogDisabled() override {
56 JNIEnv* env = base::android::AttachCurrentThread();
57 base::android::Java_TraceEvent_setEnabled(env, false);
58 }
59 };
60
61 base::LazyInstance<TraceEnabledObserver>::Leaky g_trace_enabled_state_observer_;
62
63 } // namespace
64
JNI_TraceEvent_RegisterEnabledObserver(JNIEnv * env,const JavaParamRef<jclass> & clazz)65 static void JNI_TraceEvent_RegisterEnabledObserver(
66 JNIEnv* env,
67 const JavaParamRef<jclass>& clazz) {
68 bool enabled = trace_event::TraceLog::GetInstance()->IsEnabled();
69 base::android::Java_TraceEvent_setEnabled(env, enabled);
70 trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(
71 g_trace_enabled_state_observer_.Pointer());
72 }
73
JNI_TraceEvent_StartATrace(JNIEnv * env,const JavaParamRef<jclass> & clazz)74 static void JNI_TraceEvent_StartATrace(JNIEnv* env,
75 const JavaParamRef<jclass>& clazz) {
76 base::trace_event::TraceLog::GetInstance()->StartATrace();
77 }
78
JNI_TraceEvent_StopATrace(JNIEnv * env,const JavaParamRef<jclass> & clazz)79 static void JNI_TraceEvent_StopATrace(JNIEnv* env,
80 const JavaParamRef<jclass>& clazz) {
81 base::trace_event::TraceLog::GetInstance()->StopATrace();
82 }
83
JNI_TraceEvent_Instant(JNIEnv * env,const JavaParamRef<jclass> & clazz,const JavaParamRef<jstring> & jname,const JavaParamRef<jstring> & jarg)84 static void JNI_TraceEvent_Instant(JNIEnv* env,
85 const JavaParamRef<jclass>& clazz,
86 const JavaParamRef<jstring>& jname,
87 const JavaParamRef<jstring>& jarg) {
88 TraceEventDataConverter converter(env, jname, jarg);
89 if (converter.arg()) {
90 TRACE_EVENT_COPY_INSTANT1(kJavaCategory, converter.name(),
91 TRACE_EVENT_SCOPE_THREAD,
92 converter.arg_name(), converter.arg());
93 } else {
94 TRACE_EVENT_COPY_INSTANT0(kJavaCategory, converter.name(),
95 TRACE_EVENT_SCOPE_THREAD);
96 }
97 }
98
JNI_TraceEvent_Begin(JNIEnv * env,const JavaParamRef<jclass> & clazz,const JavaParamRef<jstring> & jname,const JavaParamRef<jstring> & jarg)99 static void JNI_TraceEvent_Begin(JNIEnv* env,
100 const JavaParamRef<jclass>& clazz,
101 const JavaParamRef<jstring>& jname,
102 const JavaParamRef<jstring>& jarg) {
103 TraceEventDataConverter converter(env, jname, jarg);
104 if (converter.arg()) {
105 TRACE_EVENT_COPY_BEGIN1(kJavaCategory, converter.name(),
106 converter.arg_name(), converter.arg());
107 } else {
108 TRACE_EVENT_COPY_BEGIN0(kJavaCategory, converter.name());
109 }
110 }
111
JNI_TraceEvent_End(JNIEnv * env,const JavaParamRef<jclass> & clazz,const JavaParamRef<jstring> & jname,const JavaParamRef<jstring> & jarg)112 static void JNI_TraceEvent_End(JNIEnv* env,
113 const JavaParamRef<jclass>& clazz,
114 const JavaParamRef<jstring>& jname,
115 const JavaParamRef<jstring>& jarg) {
116 TraceEventDataConverter converter(env, jname, jarg);
117 if (converter.arg()) {
118 TRACE_EVENT_COPY_END1(kJavaCategory, converter.name(),
119 converter.arg_name(), converter.arg());
120 } else {
121 TRACE_EVENT_COPY_END0(kJavaCategory, converter.name());
122 }
123 }
124
JNI_TraceEvent_BeginToplevel(JNIEnv * env,const JavaParamRef<jclass> & clazz,const JavaParamRef<jstring> & jtarget)125 static void JNI_TraceEvent_BeginToplevel(JNIEnv* env,
126 const JavaParamRef<jclass>& clazz,
127 const JavaParamRef<jstring>& jtarget) {
128 std::string target = ConvertJavaStringToUTF8(env, jtarget);
129 TRACE_EVENT_BEGIN1(kToplevelCategory, kLooperDispatchMessage, "target",
130 target);
131 }
132
JNI_TraceEvent_EndToplevel(JNIEnv * env,const JavaParamRef<jclass> & clazz)133 static void JNI_TraceEvent_EndToplevel(JNIEnv* env,
134 const JavaParamRef<jclass>& clazz) {
135 TRACE_EVENT_END0(kToplevelCategory, kLooperDispatchMessage);
136 }
137
JNI_TraceEvent_StartAsync(JNIEnv * env,const JavaParamRef<jclass> & clazz,const JavaParamRef<jstring> & jname,jlong jid)138 static void JNI_TraceEvent_StartAsync(JNIEnv* env,
139 const JavaParamRef<jclass>& clazz,
140 const JavaParamRef<jstring>& jname,
141 jlong jid) {
142 TraceEventDataConverter converter(env, jname, nullptr);
143 TRACE_EVENT_COPY_ASYNC_BEGIN0(kJavaCategory, converter.name(), jid);
144 }
145
JNI_TraceEvent_FinishAsync(JNIEnv * env,const JavaParamRef<jclass> & clazz,const JavaParamRef<jstring> & jname,jlong jid)146 static void JNI_TraceEvent_FinishAsync(JNIEnv* env,
147 const JavaParamRef<jclass>& clazz,
148 const JavaParamRef<jstring>& jname,
149 jlong jid) {
150 TraceEventDataConverter converter(env, jname, nullptr);
151 TRACE_EVENT_COPY_ASYNC_END0(kJavaCategory, converter.name(), jid);
152 }
153
154 } // namespace android
155 } // namespace base
156