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