OSDN Git Service

Expose async & counter publicly
[android-x86/frameworks-base.git] / core / java / android / os / Trace.java
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 package android.os;
18
19 import com.android.internal.os.Zygote;
20
21 import dalvik.annotation.optimization.FastNative;
22
23 /**
24  * Writes trace events to the system trace buffer.  These trace events can be
25  * collected and visualized using the Systrace tool.
26  *
27  * <p>This tracing mechanism is independent of the method tracing mechanism
28  * offered by {@link Debug#startMethodTracing}.  In particular, it enables
29  * tracing of events that occur across multiple processes.
30  * <p>For information about using the Systrace tool, read <a
31  * href="{@docRoot}tools/debugging/systrace.html">Analyzing Display and Performance
32  * with Systrace</a>.
33  */
34 public final class Trace {
35     /*
36      * Writes trace events to the kernel trace buffer.  These trace events can be
37      * collected using the "atrace" program for offline analysis.
38      */
39
40     private static final String TAG = "Trace";
41
42     // These tags must be kept in sync with system/core/include/cutils/trace.h.
43     // They should also be added to frameworks/native/cmds/atrace/atrace.cpp.
44     /** @hide */
45     public static final long TRACE_TAG_NEVER = 0;
46     /** @hide */
47     public static final long TRACE_TAG_ALWAYS = 1L << 0;
48     /** @hide */
49     public static final long TRACE_TAG_GRAPHICS = 1L << 1;
50     /** @hide */
51     public static final long TRACE_TAG_INPUT = 1L << 2;
52     /** @hide */
53     public static final long TRACE_TAG_VIEW = 1L << 3;
54     /** @hide */
55     public static final long TRACE_TAG_WEBVIEW = 1L << 4;
56     /** @hide */
57     public static final long TRACE_TAG_WINDOW_MANAGER = 1L << 5;
58     /** @hide */
59     public static final long TRACE_TAG_ACTIVITY_MANAGER = 1L << 6;
60     /** @hide */
61     public static final long TRACE_TAG_SYNC_MANAGER = 1L << 7;
62     /** @hide */
63     public static final long TRACE_TAG_AUDIO = 1L << 8;
64     /** @hide */
65     public static final long TRACE_TAG_VIDEO = 1L << 9;
66     /** @hide */
67     public static final long TRACE_TAG_CAMERA = 1L << 10;
68     /** @hide */
69     public static final long TRACE_TAG_HAL = 1L << 11;
70     /** @hide */
71     public static final long TRACE_TAG_APP = 1L << 12;
72     /** @hide */
73     public static final long TRACE_TAG_RESOURCES = 1L << 13;
74     /** @hide */
75     public static final long TRACE_TAG_DALVIK = 1L << 14;
76     /** @hide */
77     public static final long TRACE_TAG_RS = 1L << 15;
78     /** @hide */
79     public static final long TRACE_TAG_BIONIC = 1L << 16;
80     /** @hide */
81     public static final long TRACE_TAG_POWER = 1L << 17;
82     /** @hide */
83     public static final long TRACE_TAG_PACKAGE_MANAGER = 1L << 18;
84     /** @hide */
85     public static final long TRACE_TAG_SYSTEM_SERVER = 1L << 19;
86     /** @hide */
87     public static final long TRACE_TAG_DATABASE = 1L << 20;
88     /** @hide */
89     public static final long TRACE_TAG_NETWORK = 1L << 21;
90     /** @hide */
91     public static final long TRACE_TAG_ADB = 1L << 22;
92     /** @hide */
93     public static final long TRACE_TAG_VIBRATOR = 1L << 23;
94     /** @hide */
95     public static final long TRACE_TAG_AIDL = 1L << 24;
96     /** @hide */
97     public static final long TRACE_TAG_NNAPI = 1L << 25;
98
99     private static final long TRACE_TAG_NOT_READY = 1L << 63;
100     private static final int MAX_SECTION_NAME_LEN = 127;
101
102     // Must be volatile to avoid word tearing.
103     private static volatile long sEnabledTags = TRACE_TAG_NOT_READY;
104
105     private static int sZygoteDebugFlags = 0;
106
107     private static native long nativeGetEnabledTags();
108     private static native void nativeSetAppTracingAllowed(boolean allowed);
109     private static native void nativeSetTracingEnabled(boolean allowed);
110
111     @FastNative
112     private static native void nativeTraceCounter(long tag, String name, int value);
113     @FastNative
114     private static native void nativeTraceBegin(long tag, String name);
115     @FastNative
116     private static native void nativeTraceEnd(long tag);
117     @FastNative
118     private static native void nativeAsyncTraceBegin(long tag, String name, int cookie);
119     @FastNative
120     private static native void nativeAsyncTraceEnd(long tag, String name, int cookie);
121
122     static {
123         // We configure two separate change callbacks, one in Trace.cpp and one here.  The
124         // native callback reads the tags from the system property, and this callback
125         // reads the value that the native code retrieved.  It's essential that the native
126         // callback executes first.
127         //
128         // The system provides ordering through a priority level.  Callbacks made through
129         // SystemProperties.addChangeCallback currently have a negative priority, while
130         // our native code is using a priority of zero.
131         SystemProperties.addChangeCallback(() -> {
132             cacheEnabledTags();
133             if ((sZygoteDebugFlags & Zygote.DEBUG_JAVA_DEBUGGABLE) != 0) {
134                 traceCounter(TRACE_TAG_ALWAYS, "java_debuggable", 1);
135             }
136         });
137     }
138
139     private Trace() {
140     }
141
142     /**
143      * Caches a copy of the enabled-tag bits.  The "master" copy is held by the native code,
144      * and comes from the PROPERTY_TRACE_TAG_ENABLEFLAGS property.
145      * <p>
146      * If the native code hasn't yet read the property, we will cause it to do one-time
147      * initialization.  We don't want to do this during class init, because this class is
148      * preloaded, so all apps would be stuck with whatever the zygote saw.  (The zygote
149      * doesn't see the system-property update broadcasts.)
150      * <p>
151      * We want to defer initialization until the first use by an app, post-zygote.
152      * <p>
153      * We're okay if multiple threads call here simultaneously -- the native state is
154      * synchronized, and sEnabledTags is volatile (prevents word tearing).
155      */
156     private static long cacheEnabledTags() {
157         long tags = nativeGetEnabledTags();
158         sEnabledTags = tags;
159         return tags;
160     }
161
162     /**
163      * Returns true if a trace tag is enabled.
164      *
165      * @param traceTag The trace tag to check.
166      * @return True if the trace tag is valid.
167      *
168      * @hide
169      */
170     public static boolean isTagEnabled(long traceTag) {
171         long tags = sEnabledTags;
172         if (tags == TRACE_TAG_NOT_READY) {
173             tags = cacheEnabledTags();
174         }
175         return (tags & traceTag) != 0;
176     }
177
178     /**
179      * Writes trace message to indicate the value of a given counter.
180      *
181      * @param traceTag The trace tag.
182      * @param counterName The counter name to appear in the trace.
183      * @param counterValue The counter value.
184      *
185      * @hide
186      */
187     public static void traceCounter(long traceTag, String counterName, int counterValue) {
188         if (isTagEnabled(traceTag)) {
189             nativeTraceCounter(traceTag, counterName, counterValue);
190         }
191     }
192
193     /**
194      * Set whether application tracing is allowed for this process.  This is intended to be set
195      * once at application start-up time based on whether the application is debuggable.
196      *
197      * @hide
198      */
199     public static void setAppTracingAllowed(boolean allowed) {
200         nativeSetAppTracingAllowed(allowed);
201
202         // Setting whether app tracing is allowed may change the tags, so we update the cached
203         // tags here.
204         cacheEnabledTags();
205     }
206
207     /**
208      * Set whether tracing is enabled in this process.  Tracing is disabled shortly after Zygote
209      * initializes and re-enabled after processes fork from Zygote.  This is done because Zygote
210      * has no way to be notified about changes to the tracing tags, and if Zygote ever reads and
211      * caches the tracing tags, forked processes will inherit those stale tags.
212      *
213      * @hide
214      */
215     public static void setTracingEnabled(boolean enabled, int debugFlags) {
216         nativeSetTracingEnabled(enabled);
217         sZygoteDebugFlags = debugFlags;
218
219         // Setting whether tracing is enabled may change the tags, so we update the cached tags
220         // here.
221         cacheEnabledTags();
222     }
223
224     /**
225      * Writes a trace message to indicate that a given section of code has
226      * begun. Must be followed by a call to {@link #traceEnd} using the same
227      * tag.
228      *
229      * @param traceTag The trace tag.
230      * @param methodName The method name to appear in the trace.
231      *
232      * @hide
233      */
234     public static void traceBegin(long traceTag, String methodName) {
235         if (isTagEnabled(traceTag)) {
236             nativeTraceBegin(traceTag, methodName);
237         }
238     }
239
240     /**
241      * Writes a trace message to indicate that the current method has ended.
242      * Must be called exactly once for each call to {@link #traceBegin} using the same tag.
243      *
244      * @param traceTag The trace tag.
245      *
246      * @hide
247      */
248     public static void traceEnd(long traceTag) {
249         if (isTagEnabled(traceTag)) {
250             nativeTraceEnd(traceTag);
251         }
252     }
253
254     /**
255      * Writes a trace message to indicate that a given section of code has
256      * begun. Must be followed by a call to {@link #asyncTraceEnd} using the same
257      * tag. Unlike {@link #traceBegin(long, String)} and {@link #traceEnd(long)},
258      * asynchronous events do not need to be nested. The name and cookie used to
259      * begin an event must be used to end it.
260      *
261      * @param traceTag The trace tag.
262      * @param methodName The method name to appear in the trace.
263      * @param cookie Unique identifier for distinguishing simultaneous events
264      *
265      * @hide
266      */
267     public static void asyncTraceBegin(long traceTag, String methodName, int cookie) {
268         if (isTagEnabled(traceTag)) {
269             nativeAsyncTraceBegin(traceTag, methodName, cookie);
270         }
271     }
272
273     /**
274      * Writes a trace message to indicate that the current method has ended.
275      * Must be called exactly once for each call to {@link #asyncTraceBegin(long, String, int)}
276      * using the same tag, name and cookie.
277      *
278      * @param traceTag The trace tag.
279      * @param methodName The method name to appear in the trace.
280      * @param cookie Unique identifier for distinguishing simultaneous events
281      *
282      * @hide
283      */
284     public static void asyncTraceEnd(long traceTag, String methodName, int cookie) {
285         if (isTagEnabled(traceTag)) {
286             nativeAsyncTraceEnd(traceTag, methodName, cookie);
287         }
288     }
289
290     /**
291      * Checks whether or not tracing is currently enabled. This is useful to avoid intermediate
292      * string creation for trace sections that require formatting. It is not necessary
293      * to guard all Trace method calls as they internally already check this. However it is
294      * recommended to use this to prevent creating any temporary objects that would then be
295      * passed to those methods to reduce runtime cost when tracing isn't enabled.
296      *
297      * @return true if tracing is currently enabled, false otherwise
298      */
299     public static boolean isEnabled() {
300         return isTagEnabled(TRACE_TAG_APP);
301     }
302
303     /**
304      * Writes a trace message to indicate that a given section of code has begun. This call must
305      * be followed by a corresponding call to {@link #endSection()} on the same thread.
306      *
307      * <p class="note"> At this time the vertical bar character '|', newline character '\n', and
308      * null character '\0' are used internally by the tracing mechanism.  If sectionName contains
309      * these characters they will be replaced with a space character in the trace.
310      *
311      * @param sectionName The name of the code section to appear in the trace.  This may be at
312      * most 127 Unicode code units long.
313      */
314     public static void beginSection(String sectionName) {
315         if (isTagEnabled(TRACE_TAG_APP)) {
316             if (sectionName.length() > MAX_SECTION_NAME_LEN) {
317                 throw new IllegalArgumentException("sectionName is too long");
318             }
319             nativeTraceBegin(TRACE_TAG_APP, sectionName);
320         }
321     }
322
323     /**
324      * Writes a trace message to indicate that a given section of code has ended. This call must
325      * be preceeded by a corresponding call to {@link #beginSection(String)}. Calling this method
326      * will mark the end of the most recently begun section of code, so care must be taken to
327      * ensure that beginSection / endSection pairs are properly nested and called from the same
328      * thread.
329      */
330     public static void endSection() {
331         if (isTagEnabled(TRACE_TAG_APP)) {
332             nativeTraceEnd(TRACE_TAG_APP);
333         }
334     }
335
336     /**
337      * Writes a trace message to indicate that a given section of code has
338      * begun. Must be followed by a call to {@link #endAsyncSection(String, int)} with the same
339      * methodName and cookie. Unlike {@link #beginSection(String)} and {@link #endSection()},
340      * asynchronous events do not need to be nested. The name and cookie used to
341      * begin an event must be used to end it.
342      *
343      * @param methodName The method name to appear in the trace.
344      * @param cookie Unique identifier for distinguishing simultaneous events
345      */
346     public static void beginAsyncSection(String methodName, int cookie) {
347         asyncTraceBegin(TRACE_TAG_APP, methodName, cookie);
348     }
349
350     /**
351      * Writes a trace message to indicate that the current method has ended.
352      * Must be called exactly once for each call to {@link #beginAsyncSection(String, int)}
353      * using the same name and cookie.
354      *
355      * @param methodName The method name to appear in the trace.
356      * @param cookie Unique identifier for distinguishing simultaneous events
357      */
358     public static void endAsyncSection(String methodName, int cookie) {
359         asyncTraceEnd(TRACE_TAG_APP, methodName, cookie);
360     }
361
362     /**
363      * Writes trace message to indicate the value of a given counter.
364      *
365      * @param counterName The counter name to appear in the trace.
366      * @param counterValue The counter value.
367      */
368     public static void setCounter(String counterName, int counterValue) {
369         if (isTagEnabled(TRACE_TAG_APP)) {
370             nativeTraceCounter(TRACE_TAG_APP, counterName, counterValue);
371         }
372     }
373 }