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/debug/trace_event.h"
     12 #include "base/debug/trace_event_impl.h"
     13 #include "base/lazy_instance.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:
     28   TraceEventDataConverter(JNIEnv* env,
     29                           jstring jname,
     30                           jstring jarg)
     31       : env_(env),
     32         jname_(jname),
     33         jarg_(jarg),
     34         name_(env->GetStringUTFChars(jname, NULL)),
     35         arg_(jarg ? env->GetStringUTFChars(jarg, NULL) : NULL) {
     36   }
     37   ~TraceEventDataConverter() {
     38     env_->ReleaseStringUTFChars(jname_, name_);
     39     if (jarg_)
     40       env_->ReleaseStringUTFChars(jarg_, arg_);
     41   }
     42 
     43   // Return saves values to pass to TRACE_EVENT macros.
     44   const char* name() { return name_; }
     45   const char* arg_name() { return arg_ ? "arg" : NULL; }
     46   const char* arg() { return arg_; }
     47 
     48  private:
     49   JNIEnv* env_;
     50   jstring jname_;
     51   jstring jarg_;
     52   const char* name_;
     53   const char* arg_;
     54 
     55   DISALLOW_COPY_AND_ASSIGN(TraceEventDataConverter);
     56 };
     57 
     58 class TraceEnabledObserver : public debug::TraceLog::EnabledStateObserver {
     59   public:
     60     virtual void OnTraceLogEnabled() OVERRIDE {
     61       JNIEnv* env = base::android::AttachCurrentThread();
     62       base::android::Java_TraceEvent_setEnabled(env, true);
     63     }
     64     virtual void OnTraceLogDisabled() OVERRIDE {
     65       JNIEnv* env = base::android::AttachCurrentThread();
     66       base::android::Java_TraceEvent_setEnabled(env, false);
     67     }
     68 };
     69 
     70 base::LazyInstance<TraceEnabledObserver>::Leaky g_trace_enabled_state_observer_;
     71 
     72 }  // namespace
     73 
     74 static void RegisterEnabledObserver(JNIEnv* env, jclass clazz) {
     75   bool enabled = debug::TraceLog::GetInstance()->IsEnabled();
     76   base::android::Java_TraceEvent_setEnabled(env, enabled);
     77   debug::TraceLog::GetInstance()->AddEnabledStateObserver(
     78       g_trace_enabled_state_observer_.Pointer());
     79 }
     80 
     81 static void StartATrace(JNIEnv* env, jclass clazz) {
     82   base::debug::TraceLog::GetInstance()->StartATrace();
     83 }
     84 
     85 static void StopATrace(JNIEnv* env, jclass clazz) {
     86   base::debug::TraceLog::GetInstance()->StopATrace();
     87 }
     88 
     89 static void Instant(JNIEnv* env, jclass clazz,
     90                     jstring jname, jstring jarg) {
     91   TraceEventDataConverter converter(env, jname, jarg);
     92   if (converter.arg()) {
     93     TRACE_EVENT_COPY_INSTANT1(kJavaCategory, converter.name(),
     94                               TRACE_EVENT_SCOPE_THREAD,
     95                               converter.arg_name(), converter.arg());
     96   } else {
     97     TRACE_EVENT_COPY_INSTANT0(kJavaCategory, converter.name(),
     98                               TRACE_EVENT_SCOPE_THREAD);
     99   }
    100 }
    101 
    102 static void Begin(JNIEnv* env, jclass clazz,
    103                   jstring jname, jstring jarg) {
    104   TraceEventDataConverter converter(env, jname, jarg);
    105   if (converter.arg()) {
    106     TRACE_EVENT_COPY_BEGIN1(kJavaCategory, converter.name(),
    107                        converter.arg_name(), converter.arg());
    108   } else {
    109     TRACE_EVENT_COPY_BEGIN0(kJavaCategory, converter.name());
    110   }
    111 }
    112 
    113 static void End(JNIEnv* env, jclass clazz,
    114                 jstring jname, 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, jclass clazz) {
    125   TRACE_EVENT_BEGIN0(kToplevelCategory, kLooperDispatchMessage);
    126 }
    127 
    128 static void EndToplevel(JNIEnv* env, jclass clazz) {
    129   TRACE_EVENT_END0(kToplevelCategory, kLooperDispatchMessage);
    130 }
    131 
    132 static void StartAsync(JNIEnv* env, jclass clazz,
    133                        jstring jname, jlong jid, jstring jarg) {
    134   TraceEventDataConverter converter(env, jname, jarg);
    135   if (converter.arg()) {
    136     TRACE_EVENT_COPY_ASYNC_BEGIN1(kJavaCategory,
    137                                   converter.name(),
    138                                   jid,
    139                                   converter.arg_name(),
    140                                   converter.arg());
    141   } else {
    142     TRACE_EVENT_COPY_ASYNC_BEGIN0(kJavaCategory,
    143                                   converter.name(),
    144                                   jid);
    145   }
    146 }
    147 
    148 static void FinishAsync(JNIEnv* env, jclass clazz,
    149                         jstring jname, jlong jid, jstring jarg) {
    150   TraceEventDataConverter converter(env, jname, jarg);
    151   if (converter.arg()) {
    152     TRACE_EVENT_COPY_ASYNC_END1(kJavaCategory,
    153                                 converter.name(),
    154                                 jid,
    155                                 converter.arg_name(),
    156                                 converter.arg());
    157   } else {
    158     TRACE_EVENT_COPY_ASYNC_END0(kJavaCategory,
    159                                 converter.name(),
    160                                 jid);
    161   }
    162 }
    163 
    164 bool RegisterTraceEvent(JNIEnv* env) {
    165   return RegisterNativesImpl(env);
    166 }
    167 
    168 }  // namespace android
    169 }  // namespace base
    170