1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "Trace"
18// #define LOG_NDEBUG 0
19
20#include <inttypes.h>
21
22#include <JNIHelp.h>
23#include <ScopedUtfChars.h>
24#include <ScopedStringChars.h>
25
26#include <utils/String8.h>
27
28#include <cutils/trace.h>
29#include <cutils/log.h>
30
31namespace android {
32
33static void sanitizeString(String8& utf8Chars) {
34    size_t size = utf8Chars.size();
35    char* str = utf8Chars.lockBuffer(size);
36    for (size_t i = 0; i < size; i++) {
37        char c = str[i];
38        if (c == '\0' || c == '\n' || c == '|') {
39            str[i] = ' ';
40        }
41    }
42    utf8Chars.unlockBuffer();
43}
44
45static jlong android_os_Trace_nativeGetEnabledTags(JNIEnv* env, jclass clazz) {
46    return atrace_get_enabled_tags();
47}
48
49static void android_os_Trace_nativeTraceCounter(JNIEnv* env, jclass clazz,
50        jlong tag, jstring nameStr, jint value) {
51    ScopedUtfChars name(env, nameStr);
52
53    ALOGV("%s: %" PRId64 " %s %d", __FUNCTION__, tag, name.c_str(), value);
54    atrace_int(tag, name.c_str(), value);
55}
56
57static void android_os_Trace_nativeTraceBegin(JNIEnv* env, jclass clazz,
58        jlong tag, jstring nameStr) {
59    ScopedStringChars jchars(env, nameStr);
60    String8 utf8Chars(reinterpret_cast<const char16_t*>(jchars.get()), jchars.size());
61    sanitizeString(utf8Chars);
62
63    ALOGV("%s: %" PRId64 " %s", __FUNCTION__, tag, utf8Chars.string());
64    atrace_begin(tag, utf8Chars.string());
65}
66
67static void android_os_Trace_nativeTraceEnd(JNIEnv* env, jclass clazz,
68        jlong tag) {
69
70    ALOGV("%s: %" PRId64, __FUNCTION__, tag);
71    atrace_end(tag);
72}
73
74static void android_os_Trace_nativeAsyncTraceBegin(JNIEnv* env, jclass clazz,
75        jlong tag, jstring nameStr, jint cookie) {
76    ScopedStringChars jchars(env, nameStr);
77    String8 utf8Chars(reinterpret_cast<const char16_t*>(jchars.get()), jchars.size());
78    sanitizeString(utf8Chars);
79
80    ALOGV("%s: %" PRId64 " %s %d", __FUNCTION__, tag, utf8Chars.string(), cookie);
81    atrace_async_begin(tag, utf8Chars.string(), cookie);
82}
83
84static void android_os_Trace_nativeAsyncTraceEnd(JNIEnv* env, jclass clazz,
85        jlong tag, jstring nameStr, jint cookie) {
86    ScopedStringChars jchars(env, nameStr);
87    String8 utf8Chars(reinterpret_cast<const char16_t*>(jchars.get()), jchars.size());
88    sanitizeString(utf8Chars);
89
90    ALOGV("%s: %" PRId64 " %s %d", __FUNCTION__, tag, utf8Chars.string(), cookie);
91    atrace_async_end(tag, utf8Chars.string(), cookie);
92}
93
94static void android_os_Trace_nativeSetAppTracingAllowed(JNIEnv* env,
95        jclass clazz, jboolean allowed) {
96    ALOGV("%s: %d", __FUNCTION__, allowed);
97
98    atrace_set_debuggable(allowed);
99}
100
101static void android_os_Trace_nativeSetTracingEnabled(JNIEnv* env,
102        jclass clazz, jboolean enabled) {
103    ALOGV("%s: %d", __FUNCTION__, enabled);
104
105    atrace_set_tracing_enabled(enabled);
106}
107
108static const JNINativeMethod gTraceMethods[] = {
109    /* name, signature, funcPtr */
110    { "nativeGetEnabledTags",
111            "()J",
112            (void*)android_os_Trace_nativeGetEnabledTags },
113    { "nativeTraceCounter",
114            "!(JLjava/lang/String;I)V",
115            (void*)android_os_Trace_nativeTraceCounter },
116    { "nativeTraceBegin",
117            "!(JLjava/lang/String;)V",
118            (void*)android_os_Trace_nativeTraceBegin },
119    { "nativeTraceEnd",
120            "!(J)V",
121            (void*)android_os_Trace_nativeTraceEnd },
122    { "nativeAsyncTraceBegin",
123            "!(JLjava/lang/String;I)V",
124            (void*)android_os_Trace_nativeAsyncTraceBegin },
125    { "nativeAsyncTraceEnd",
126            "!(JLjava/lang/String;I)V",
127            (void*)android_os_Trace_nativeAsyncTraceEnd },
128    { "nativeSetAppTracingAllowed",
129            "(Z)V",
130            (void*)android_os_Trace_nativeSetAppTracingAllowed },
131    { "nativeSetTracingEnabled",
132            "(Z)V",
133            (void*)android_os_Trace_nativeSetTracingEnabled },
134};
135
136int register_android_os_Trace(JNIEnv* env) {
137    int res = jniRegisterNativeMethods(env, "android/os/Trace",
138            gTraceMethods, NELEM(gTraceMethods));
139    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
140
141    return 0;
142}
143
144} // namespace android
145