• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
20 
21 import android.annotation.NonNull;
22 import android.annotation.SystemApi;
23 import android.compat.annotation.UnsupportedAppUsage;
24 
25 import dalvik.annotation.optimization.CriticalNative;
26 import dalvik.annotation.optimization.FastNative;
27 
28 /**
29  * Writes trace events to the system trace buffer.  These trace events can be
30  * collected and visualized using the Systrace tool.
31  *
32  * <p>This tracing mechanism is independent of the method tracing mechanism
33  * offered by {@link Debug#startMethodTracing}.  In particular, it enables
34  * tracing of events that occur across multiple processes.
35  * <p>For information about using the Systrace tool, read <a
36  * href="{@docRoot}tools/debugging/systrace.html">Analyzing Display and Performance
37  * with Systrace</a>.
38  */
39 public final class Trace {
40     /*
41      * Writes trace events to the kernel trace buffer.  These trace events can be
42      * collected using the "atrace" program for offline analysis.
43      */
44 
45     private static final String TAG = "Trace";
46 
47     // These tags must be kept in sync with system/core/include/cutils/trace.h.
48     // They should also be added to frameworks/native/cmds/atrace/atrace.cpp.
49     /** @hide */
50     public static final long TRACE_TAG_NEVER = 0;
51     /** @hide */
52     public static final long TRACE_TAG_ALWAYS = 1L << 0;
53     /** @hide */
54     public static final long TRACE_TAG_GRAPHICS = 1L << 1;
55     /** @hide */
56     public static final long TRACE_TAG_INPUT = 1L << 2;
57     /** @hide */
58     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
59     public static final long TRACE_TAG_VIEW = 1L << 3;
60     /** @hide */
61     public static final long TRACE_TAG_WEBVIEW = 1L << 4;
62     /** @hide */
63     public static final long TRACE_TAG_WINDOW_MANAGER = 1L << 5;
64     /** @hide */
65     public static final long TRACE_TAG_ACTIVITY_MANAGER = 1L << 6;
66     /** @hide */
67     public static final long TRACE_TAG_SYNC_MANAGER = 1L << 7;
68     /** @hide */
69     public static final long TRACE_TAG_AUDIO = 1L << 8;
70     /** @hide */
71     public static final long TRACE_TAG_VIDEO = 1L << 9;
72     /** @hide */
73     public static final long TRACE_TAG_CAMERA = 1L << 10;
74     /** @hide */
75     public static final long TRACE_TAG_HAL = 1L << 11;
76     /** @hide */
77     @UnsupportedAppUsage
78     public static final long TRACE_TAG_APP = 1L << 12;
79     /** @hide */
80     public static final long TRACE_TAG_RESOURCES = 1L << 13;
81     /** @hide */
82     public static final long TRACE_TAG_DALVIK = 1L << 14;
83     /** @hide */
84     public static final long TRACE_TAG_RS = 1L << 15;
85     /** @hide */
86     public static final long TRACE_TAG_BIONIC = 1L << 16;
87     /** @hide */
88     public static final long TRACE_TAG_POWER = 1L << 17;
89     /** @hide */
90     public static final long TRACE_TAG_PACKAGE_MANAGER = 1L << 18;
91     /** @hide */
92     public static final long TRACE_TAG_SYSTEM_SERVER = 1L << 19;
93     /** @hide */
94     public static final long TRACE_TAG_DATABASE = 1L << 20;
95     /** @hide */
96     @SystemApi(client = MODULE_LIBRARIES)
97     public static final long TRACE_TAG_NETWORK = 1L << 21;
98     /** @hide */
99     public static final long TRACE_TAG_ADB = 1L << 22;
100     /** @hide */
101     public static final long TRACE_TAG_VIBRATOR = 1L << 23;
102     /** @hide */
103     public static final long TRACE_TAG_AIDL = 1L << 24;
104     /** @hide */
105     public static final long TRACE_TAG_NNAPI = 1L << 25;
106     /** @hide */
107     public static final long TRACE_TAG_RRO = 1L << 26;
108     /** @hide */
109     public static final long TRACE_TAG_THERMAL = 1L << 27;
110 
111     private static final long TRACE_TAG_NOT_READY = 1L << 63;
112     /** @hide **/
113     public static final int MAX_SECTION_NAME_LEN = 127;
114 
115     // Must be volatile to avoid word tearing.
116     // This is only kept in case any apps get this by reflection but do not
117     // check the return value for null.
118     @UnsupportedAppUsage
119     private static volatile long sEnabledTags = TRACE_TAG_NOT_READY;
120 
121     private static int sZygoteDebugFlags = 0;
122 
123     @UnsupportedAppUsage
124     @CriticalNative
nativeGetEnabledTags()125     private static native long nativeGetEnabledTags();
nativeSetAppTracingAllowed(boolean allowed)126     private static native void nativeSetAppTracingAllowed(boolean allowed);
nativeSetTracingEnabled(boolean allowed)127     private static native void nativeSetTracingEnabled(boolean allowed);
128 
129     @FastNative
nativeTraceCounter(long tag, String name, long value)130     private static native void nativeTraceCounter(long tag, String name, long value);
131     @FastNative
nativeTraceBegin(long tag, String name)132     private static native void nativeTraceBegin(long tag, String name);
133     @FastNative
nativeTraceEnd(long tag)134     private static native void nativeTraceEnd(long tag);
135     @FastNative
nativeAsyncTraceBegin(long tag, String name, int cookie)136     private static native void nativeAsyncTraceBegin(long tag, String name, int cookie);
137     @FastNative
nativeAsyncTraceEnd(long tag, String name, int cookie)138     private static native void nativeAsyncTraceEnd(long tag, String name, int cookie);
139     @FastNative
nativeAsyncTraceForTrackBegin(long tag, String trackName, String name, int cookie)140     private static native void nativeAsyncTraceForTrackBegin(long tag,
141             String trackName, String name, int cookie);
142     @FastNative
nativeAsyncTraceForTrackEnd(long tag, String trackName, String name, int cookie)143     private static native void nativeAsyncTraceForTrackEnd(long tag,
144             String trackName, String name, int cookie);
145     @FastNative
nativeInstant(long tag, String name)146     private static native void nativeInstant(long tag, String name);
147     @FastNative
nativeInstantForTrack(long tag, String trackName, String name)148     private static native void nativeInstantForTrack(long tag, String trackName, String name);
149 
Trace()150     private Trace() {
151     }
152 
153     /**
154      * Returns true if a trace tag is enabled.
155      *
156      * @param traceTag The trace tag to check.
157      * @return True if the trace tag is valid.
158      *
159      * @hide
160      */
161     @UnsupportedAppUsage
162     @SystemApi(client = MODULE_LIBRARIES)
isTagEnabled(long traceTag)163     public static boolean isTagEnabled(long traceTag) {
164         long tags = nativeGetEnabledTags();
165         return (tags & traceTag) != 0;
166     }
167 
168     /**
169      * Writes trace message to indicate the value of a given counter.
170      *
171      * @param traceTag The trace tag.
172      * @param counterName The counter name to appear in the trace.
173      * @param counterValue The counter value.
174      *
175      * @hide
176      */
177     @UnsupportedAppUsage
178     @SystemApi(client = MODULE_LIBRARIES)
traceCounter(long traceTag, @NonNull String counterName, int counterValue)179     public static void traceCounter(long traceTag, @NonNull String counterName, int counterValue) {
180         if (isTagEnabled(traceTag)) {
181             nativeTraceCounter(traceTag, counterName, counterValue);
182         }
183     }
184 
185     /**
186      * From Android S, this is no-op.
187      *
188      * Before, set whether application tracing is allowed for this process.  This is intended to be
189      * set once at application start-up time based on whether the application is debuggable.
190      *
191      * @hide
192      */
193     @UnsupportedAppUsage
setAppTracingAllowed(boolean allowed)194     public static void setAppTracingAllowed(boolean allowed) {
195         nativeSetAppTracingAllowed(allowed);
196     }
197 
198     /**
199      * Set whether tracing is enabled in this process.
200      * @hide
201      */
setTracingEnabled(boolean enabled, int debugFlags)202     public static void setTracingEnabled(boolean enabled, int debugFlags) {
203         nativeSetTracingEnabled(enabled);
204         sZygoteDebugFlags = debugFlags;
205     }
206 
207     /**
208      * Writes a trace message to indicate that a given section of code has
209      * begun. Must be followed by a call to {@link #traceEnd} using the same
210      * tag.
211      *
212      * @param traceTag The trace tag.
213      * @param methodName The method name to appear in the trace.
214      *
215      * @hide
216      */
217     @UnsupportedAppUsage
218     @SystemApi(client = MODULE_LIBRARIES)
traceBegin(long traceTag, @NonNull String methodName)219     public static void traceBegin(long traceTag, @NonNull String methodName) {
220         if (isTagEnabled(traceTag)) {
221             nativeTraceBegin(traceTag, methodName);
222         }
223     }
224 
225     /**
226      * Writes a trace message to indicate that the current method has ended.
227      * Must be called exactly once for each call to {@link #traceBegin} using the same tag.
228      *
229      * @param traceTag The trace tag.
230      *
231      * @hide
232      */
233     @UnsupportedAppUsage
234     @SystemApi(client = MODULE_LIBRARIES)
traceEnd(long traceTag)235     public static void traceEnd(long traceTag) {
236         if (isTagEnabled(traceTag)) {
237             nativeTraceEnd(traceTag);
238         }
239     }
240 
241     /**
242      * Writes a trace message to indicate that a given section of code has
243      * begun. Must be followed by a call to {@link #asyncTraceEnd} using the same
244      * tag. Unlike {@link #traceBegin(long, String)} and {@link #traceEnd(long)},
245      * asynchronous events do not need to be nested. The name and cookie used to
246      * begin an event must be used to end it.
247      *
248      * @param traceTag The trace tag.
249      * @param methodName The method name to appear in the trace.
250      * @param cookie Unique identifier for distinguishing simultaneous events
251      *
252      * @hide
253      */
254     @UnsupportedAppUsage
255     @SystemApi(client = MODULE_LIBRARIES)
asyncTraceBegin(long traceTag, @NonNull String methodName, int cookie)256     public static void asyncTraceBegin(long traceTag, @NonNull String methodName, int cookie) {
257         if (isTagEnabled(traceTag)) {
258             nativeAsyncTraceBegin(traceTag, methodName, cookie);
259         }
260     }
261 
262     /**
263      * Writes a trace message to indicate that the current method has ended.
264      * Must be called exactly once for each call to {@link #asyncTraceBegin(long, String, int)}
265      * using the same tag, name and cookie.
266      *
267      * @param traceTag The trace tag.
268      * @param methodName The method name to appear in the trace.
269      * @param cookie Unique identifier for distinguishing simultaneous events
270      *
271      * @hide
272      */
273     @UnsupportedAppUsage
274     @SystemApi(client = MODULE_LIBRARIES)
asyncTraceEnd(long traceTag, @NonNull String methodName, int cookie)275     public static void asyncTraceEnd(long traceTag, @NonNull String methodName, int cookie) {
276         if (isTagEnabled(traceTag)) {
277             nativeAsyncTraceEnd(traceTag, methodName, cookie);
278         }
279     }
280 
281 
282     /**
283      * Writes a trace message to indicate that a given section of code has
284      * begun. Must be followed by a call to {@link #asyncTraceForTrackEnd} using the same
285      * tag. This function operates exactly like {@link #asyncTraceBegin(long, String, int)},
286      * except with the inclusion of a track name argument for where this method should appear.
287      *
288      * @param traceTag The trace tag.
289      * @param trackName The track where the event should appear in the trace.
290      * @param methodName The method name to appear in the trace.
291      * @param cookie Unique identifier for distinguishing simultaneous events
292      *
293      * @hide
294      */
asyncTraceForTrackBegin(long traceTag, @NonNull String trackName, @NonNull String methodName, int cookie)295     public static void asyncTraceForTrackBegin(long traceTag,
296             @NonNull String trackName, @NonNull String methodName, int cookie) {
297         if (isTagEnabled(traceTag)) {
298             nativeAsyncTraceForTrackBegin(traceTag, trackName, methodName, cookie);
299         }
300     }
301 
302     /**
303      * Writes a trace message to indicate that the current method has ended.
304      * Must be called exactly once for each call to
305      * {@link #asyncTraceForTrackBegin(long, String, String, int)}
306      * using the same tag, track name, name and cookie.
307      *
308      * @param traceTag The trace tag.
309      * @param trackName The track where the event should appear in the trace.
310      * @param methodName The method name to appear in the trace.
311      * @param cookie Unique identifier for distinguishing simultaneous events
312      *
313      * @hide
314      */
asyncTraceForTrackEnd(long traceTag, @NonNull String trackName, @NonNull String methodName, int cookie)315     public static void asyncTraceForTrackEnd(long traceTag,
316             @NonNull String trackName, @NonNull String methodName, int cookie) {
317         if (isTagEnabled(traceTag)) {
318             nativeAsyncTraceForTrackEnd(traceTag, trackName, methodName, cookie);
319         }
320     }
321 
322     /**
323      * Writes a trace message to indicate that a given section of code was invoked.
324      *
325      * @param traceTag The trace tag.
326      * @param methodName The method name to appear in the trace.
327      * @hide
328      */
instant(long traceTag, String methodName)329     public static void instant(long traceTag, String methodName) {
330         if (methodName == null) {
331             throw new IllegalArgumentException("methodName cannot be null");
332         }
333         if (isTagEnabled(traceTag)) {
334             nativeInstant(traceTag, methodName);
335         }
336     }
337 
338     /**
339      * Writes a trace message to indicate that a given section of code was invoked.
340      *
341      * @param traceTag The trace tag.
342      * @param trackName The track where the event should appear in the trace.
343      * @param methodName The method name to appear in the trace.
344      * @hide
345      */
instantForTrack(long traceTag, String trackName, String methodName)346     public static void instantForTrack(long traceTag, String trackName, String methodName) {
347         if (trackName == null) {
348             throw new IllegalArgumentException("trackName cannot be null");
349         }
350         if (methodName == null) {
351             throw new IllegalArgumentException("methodName cannot be null");
352         }
353         if (isTagEnabled(traceTag)) {
354             nativeInstantForTrack(traceTag, trackName, methodName);
355         }
356     }
357 
358     /**
359      * Checks whether or not tracing is currently enabled. This is useful to avoid intermediate
360      * string creation for trace sections that require formatting. It is not necessary
361      * to guard all Trace method calls as they internally already check this. However it is
362      * recommended to use this to prevent creating any temporary objects that would then be
363      * passed to those methods to reduce runtime cost when tracing isn't enabled.
364      *
365      * @return true if tracing is currently enabled, false otherwise
366      */
isEnabled()367     public static boolean isEnabled() {
368         return isTagEnabled(TRACE_TAG_APP);
369     }
370 
371     /**
372      * Writes a trace message to indicate that a given section of code has begun. This call must
373      * be followed by a corresponding call to {@link #endSection()} on the same thread.
374      *
375      * <p class="note"> At this time the vertical bar character '|', newline character '\n', and
376      * null character '\0' are used internally by the tracing mechanism.  If sectionName contains
377      * these characters they will be replaced with a space character in the trace.
378      *
379      * @param sectionName The name of the code section to appear in the trace.  This may be at
380      * most 127 Unicode code units long.
381      */
beginSection(@onNull String sectionName)382     public static void beginSection(@NonNull String sectionName) {
383         if (isTagEnabled(TRACE_TAG_APP)) {
384             if (sectionName.length() > MAX_SECTION_NAME_LEN) {
385                 throw new IllegalArgumentException("sectionName is too long");
386             }
387             nativeTraceBegin(TRACE_TAG_APP, sectionName);
388         }
389     }
390 
391     /**
392      * Writes a trace message to indicate that a given section of code has ended. This call must
393      * be preceeded by a corresponding call to {@link #beginSection(String)}. Calling this method
394      * will mark the end of the most recently begun section of code, so care must be taken to
395      * ensure that beginSection / endSection pairs are properly nested and called from the same
396      * thread.
397      */
endSection()398     public static void endSection() {
399         if (isTagEnabled(TRACE_TAG_APP)) {
400             nativeTraceEnd(TRACE_TAG_APP);
401         }
402     }
403 
404     /**
405      * Writes a trace message to indicate that a given section of code has
406      * begun. Must be followed by a call to {@link #endAsyncSection(String, int)} with the same
407      * methodName and cookie. Unlike {@link #beginSection(String)} and {@link #endSection()},
408      * asynchronous events do not need to be nested. The name and cookie used to
409      * begin an event must be used to end it.
410      *
411      * @param methodName The method name to appear in the trace.
412      * @param cookie Unique identifier for distinguishing simultaneous events
413      */
beginAsyncSection(@onNull String methodName, int cookie)414     public static void beginAsyncSection(@NonNull String methodName, int cookie) {
415         asyncTraceBegin(TRACE_TAG_APP, methodName, cookie);
416     }
417 
418     /**
419      * Writes a trace message to indicate that the current method has ended.
420      * Must be called exactly once for each call to {@link #beginAsyncSection(String, int)}
421      * using the same name and cookie.
422      *
423      * @param methodName The method name to appear in the trace.
424      * @param cookie Unique identifier for distinguishing simultaneous events
425      */
endAsyncSection(@onNull String methodName, int cookie)426     public static void endAsyncSection(@NonNull String methodName, int cookie) {
427         asyncTraceEnd(TRACE_TAG_APP, methodName, cookie);
428     }
429 
430     /**
431      * Writes trace message to indicate the value of a given counter.
432      *
433      * @param counterName The counter name to appear in the trace.
434      * @param counterValue The counter value.
435      */
setCounter(@onNull String counterName, long counterValue)436     public static void setCounter(@NonNull String counterName, long counterValue) {
437         if (isTagEnabled(TRACE_TAG_APP)) {
438             nativeTraceCounter(TRACE_TAG_APP, counterName, counterValue);
439         }
440     }
441 }
442