Trace.java revision f9c7d6bc15b68393c1f0aa85c3c023c31244c3f2
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
17package android.os;
18
19import android.util.Log;
20
21/**
22 * Writes trace events to the system trace buffer.  These trace events can be
23 * collected and visualized using the Systrace tool.
24 *
25 * This tracing mechanism is independent of the method tracing mechanism
26 * offered by {@link Debug#startMethodTracing}.  In particular, it enables
27 * tracing of events that occur across multiple processes.
28 *
29 * @hide
30 */
31public final class Trace {
32    /*
33     * Writes trace events to the kernel trace buffer.  These trace events can be
34     * collected using the "atrace" program for offline analysis.
35     */
36
37    private static final String TAG = "Trace";
38
39    // These tags must be kept in sync with system/core/include/cutils/trace.h.
40    /** @hide */
41    public static final long TRACE_TAG_NEVER = 0;
42    /** @hide */
43    public static final long TRACE_TAG_ALWAYS = 1L << 0;
44    /** @hide */
45    public static final long TRACE_TAG_GRAPHICS = 1L << 1;
46    /** @hide */
47    public static final long TRACE_TAG_INPUT = 1L << 2;
48    /** @hide */
49    public static final long TRACE_TAG_VIEW = 1L << 3;
50    /** @hide */
51    public static final long TRACE_TAG_WEBVIEW = 1L << 4;
52    /** @hide */
53    public static final long TRACE_TAG_WINDOW_MANAGER = 1L << 5;
54    /** @hide */
55    public static final long TRACE_TAG_ACTIVITY_MANAGER = 1L << 6;
56    /** @hide */
57    public static final long TRACE_TAG_SYNC_MANAGER = 1L << 7;
58    /** @hide */
59    public static final long TRACE_TAG_AUDIO = 1L << 8;
60    /** @hide */
61    public static final long TRACE_TAG_VIDEO = 1L << 9;
62    /** @hide */
63    public static final long TRACE_TAG_CAMERA = 1L << 10;
64    /** @hide */
65    public static final long TRACE_TAG_HAL = 1L << 11;
66    /** @hide */
67    public static final long TRACE_TAG_APP = 1L << 12;
68
69    private static final long TRACE_TAG_NOT_READY = 1L << 63;
70    private static final int MAX_SECTION_NAME_LEN = 127;
71
72    // Must be volatile to avoid word tearing.
73    private static volatile long sEnabledTags = TRACE_TAG_NOT_READY;
74
75    private static native long nativeGetEnabledTags();
76    private static native void nativeTraceCounter(long tag, String name, int value);
77    private static native void nativeTraceBegin(long tag, String name);
78    private static native void nativeTraceEnd(long tag);
79    private static native void nativeSetAppTracingAllowed(boolean allowed);
80
81    static {
82        // We configure two separate change callbacks, one in Trace.cpp and one here.  The
83        // native callback reads the tags from the system property, and this callback
84        // reads the value that the native code retrieved.  It's essential that the native
85        // callback executes first.
86        //
87        // The system provides ordering through a priority level.  Callbacks made through
88        // SystemProperties.addChangeCallback currently have a negative priority, while
89        // our native code is using a priority of zero.
90        SystemProperties.addChangeCallback(new Runnable() {
91            @Override public void run() {
92                cacheEnabledTags();
93            }
94        });
95    }
96
97    private Trace() {
98    }
99
100    /**
101     * Caches a copy of the enabled-tag bits.  The "master" copy is held by the native code,
102     * and comes from the PROPERTY_TRACE_TAG_ENABLEFLAGS property.
103     * <p>
104     * If the native code hasn't yet read the property, we will cause it to do one-time
105     * initialization.  We don't want to do this during class init, because this class is
106     * preloaded, so all apps would be stuck with whatever the zygote saw.  (The zygote
107     * doesn't see the system-property update broadcasts.)
108     * <p>
109     * We want to defer initialization until the first use by an app, post-zygote.
110     * <p>
111     * We're okay if multiple threads call here simultaneously -- the native state is
112     * synchronized, and sEnabledTags is volatile (prevents word tearing).
113     */
114    private static long cacheEnabledTags() {
115        long tags = nativeGetEnabledTags();
116        if (tags == TRACE_TAG_NOT_READY) {
117            Log.w(TAG, "Unexpected value from nativeGetEnabledTags: " + tags);
118            // keep going
119        }
120        sEnabledTags = tags;
121        return tags;
122    }
123
124    /**
125     * Returns true if a trace tag is enabled.
126     *
127     * @param traceTag The trace tag to check.
128     * @return True if the trace tag is valid.
129     *
130     * @hide
131     */
132    public static boolean isTagEnabled(long traceTag) {
133        long tags = sEnabledTags;
134        if (tags == TRACE_TAG_NOT_READY) {
135            tags = cacheEnabledTags();
136        }
137        return (tags & traceTag) != 0;
138    }
139
140    /**
141     * Writes trace message to indicate the value of a given counter.
142     *
143     * @param traceTag The trace tag.
144     * @param counterName The counter name to appear in the trace.
145     * @param counterValue The counter value.
146     *
147     * @hide
148     */
149    public static void traceCounter(long traceTag, String counterName, int counterValue) {
150        if (isTagEnabled(traceTag)) {
151            nativeTraceCounter(traceTag, counterName, counterValue);
152        }
153    }
154
155    /**
156     * Set whether application tracing is allowed for this process.  This is intended to be set
157     * once at application start-up time based on whether the application is debuggable.
158     *
159     * @hide
160     */
161    public static void setAppTracingAllowed(boolean allowed) {
162        nativeSetAppTracingAllowed(allowed);
163
164        // Setting whether app tracing is allowed may change the tags, so we update the cached
165        // tags here.
166        cacheEnabledTags();
167    }
168
169    /**
170     * Writes a trace message to indicate that a given section of code has
171     * begun. Must be followed by a call to {@link #traceEnd} using the same
172     * tag.
173     *
174     * @param traceTag The trace tag.
175     * @param methodName The method name to appear in the trace.
176     *
177     * @hide
178     */
179    public static void traceBegin(long traceTag, String methodName) {
180        if (isTagEnabled(traceTag)) {
181            nativeTraceBegin(traceTag, methodName);
182        }
183    }
184
185    /**
186     * Writes a trace message to indicate that the current method has ended.
187     * Must be called exactly once for each call to {@link #traceBegin} using the same tag.
188     *
189     * @param traceTag The trace tag.
190     *
191     * @hide
192     */
193    public static void traceEnd(long traceTag) {
194        if (isTagEnabled(traceTag)) {
195            nativeTraceEnd(traceTag);
196        }
197    }
198
199    /**
200     * Writes a trace message to indicate that a given section of code has begun. This call must
201     * be followed by a corresponding call to {@link #traceEnd()} on the same thread.
202     *
203     * <p class="note"> At this time the vertical bar character '|', newline character '\n', and
204     * null character '\0' are used internally by the tracing mechanism.  If sectionName contains
205     * these characters they will be replaced with a space character in the trace.
206     *
207     * @param sectionName The name of the code section to appear in the trace.  This may be at
208     * most 127 Unicode code units long.
209     *
210     * @hide
211     */
212    public static void traceBegin(String sectionName) {
213        if (isTagEnabled(TRACE_TAG_APP)) {
214            if (sectionName.length() > MAX_SECTION_NAME_LEN) {
215                throw new IllegalArgumentException("sectionName is too long");
216            }
217            nativeTraceBegin(TRACE_TAG_APP, sectionName);
218        }
219    }
220
221    /**
222     * Writes a trace message to indicate that a given section of code has ended. This call must
223     * be preceeded by a corresponding call to {@link #traceBegin(String)}. Calling this method
224     * will mark the end of the most recently begun section of code, so care must be taken to
225     * ensure that traceBegin / traceEnd pairs are properly nested and called from the same thread.
226     *
227     * @hide
228     */
229    public static void traceEnd() {
230        if (isTagEnabled(TRACE_TAG_APP)) {
231            nativeTraceEnd(TRACE_TAG_APP);
232        }
233    }
234}
235