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