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 com.android.internal.os.Zygote;
20
21import 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 */
34public 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
97    private static final long TRACE_TAG_NOT_READY = 1L << 63;
98    private static final int MAX_SECTION_NAME_LEN = 127;
99
100    // Must be volatile to avoid word tearing.
101    private static volatile long sEnabledTags = TRACE_TAG_NOT_READY;
102
103    private static int sZygoteDebugFlags = 0;
104
105    private static native long nativeGetEnabledTags();
106    private static native void nativeSetAppTracingAllowed(boolean allowed);
107    private static native void nativeSetTracingEnabled(boolean allowed);
108
109    @FastNative
110    private static native void nativeTraceCounter(long tag, String name, int value);
111    @FastNative
112    private static native void nativeTraceBegin(long tag, String name);
113    @FastNative
114    private static native void nativeTraceEnd(long tag);
115    @FastNative
116    private static native void nativeAsyncTraceBegin(long tag, String name, int cookie);
117    @FastNative
118    private static native void nativeAsyncTraceEnd(long tag, String name, int cookie);
119
120    static {
121        // We configure two separate change callbacks, one in Trace.cpp and one here.  The
122        // native callback reads the tags from the system property, and this callback
123        // reads the value that the native code retrieved.  It's essential that the native
124        // callback executes first.
125        //
126        // The system provides ordering through a priority level.  Callbacks made through
127        // SystemProperties.addChangeCallback currently have a negative priority, while
128        // our native code is using a priority of zero.
129        SystemProperties.addChangeCallback(() -> {
130            cacheEnabledTags();
131            if ((sZygoteDebugFlags & Zygote.DEBUG_JAVA_DEBUGGABLE) != 0) {
132                traceCounter(TRACE_TAG_ALWAYS, "java_debuggable", 1);
133            }
134        });
135    }
136
137    private Trace() {
138    }
139
140    /**
141     * Caches a copy of the enabled-tag bits.  The "master" copy is held by the native code,
142     * and comes from the PROPERTY_TRACE_TAG_ENABLEFLAGS property.
143     * <p>
144     * If the native code hasn't yet read the property, we will cause it to do one-time
145     * initialization.  We don't want to do this during class init, because this class is
146     * preloaded, so all apps would be stuck with whatever the zygote saw.  (The zygote
147     * doesn't see the system-property update broadcasts.)
148     * <p>
149     * We want to defer initialization until the first use by an app, post-zygote.
150     * <p>
151     * We're okay if multiple threads call here simultaneously -- the native state is
152     * synchronized, and sEnabledTags is volatile (prevents word tearing).
153     */
154    private static long cacheEnabledTags() {
155        long tags = nativeGetEnabledTags();
156        sEnabledTags = tags;
157        return tags;
158    }
159
160    /**
161     * Returns true if a trace tag is enabled.
162     *
163     * @param traceTag The trace tag to check.
164     * @return True if the trace tag is valid.
165     *
166     * @hide
167     */
168    public static boolean isTagEnabled(long traceTag) {
169        long tags = sEnabledTags;
170        if (tags == TRACE_TAG_NOT_READY) {
171            tags = cacheEnabledTags();
172        }
173        return (tags & traceTag) != 0;
174    }
175
176    /**
177     * Writes trace message to indicate the value of a given counter.
178     *
179     * @param traceTag The trace tag.
180     * @param counterName The counter name to appear in the trace.
181     * @param counterValue The counter value.
182     *
183     * @hide
184     */
185    public static void traceCounter(long traceTag, String counterName, int counterValue) {
186        if (isTagEnabled(traceTag)) {
187            nativeTraceCounter(traceTag, counterName, counterValue);
188        }
189    }
190
191    /**
192     * Set whether application tracing is allowed for this process.  This is intended to be set
193     * once at application start-up time based on whether the application is debuggable.
194     *
195     * @hide
196     */
197    public static void setAppTracingAllowed(boolean allowed) {
198        nativeSetAppTracingAllowed(allowed);
199
200        // Setting whether app tracing is allowed may change the tags, so we update the cached
201        // tags here.
202        cacheEnabledTags();
203    }
204
205    /**
206     * Set whether tracing is enabled in this process.  Tracing is disabled shortly after Zygote
207     * initializes and re-enabled after processes fork from Zygote.  This is done because Zygote
208     * has no way to be notified about changes to the tracing tags, and if Zygote ever reads and
209     * caches the tracing tags, forked processes will inherit those stale tags.
210     *
211     * @hide
212     */
213    public static void setTracingEnabled(boolean enabled, int debugFlags) {
214        nativeSetTracingEnabled(enabled);
215        sZygoteDebugFlags = debugFlags;
216
217        // Setting whether tracing is enabled may change the tags, so we update the cached tags
218        // here.
219        cacheEnabledTags();
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 #traceEnd} using the same
225     * tag.
226     *
227     * @param traceTag The trace tag.
228     * @param methodName The method name to appear in the trace.
229     *
230     * @hide
231     */
232    public static void traceBegin(long traceTag, String methodName) {
233        if (isTagEnabled(traceTag)) {
234            nativeTraceBegin(traceTag, methodName);
235        }
236    }
237
238    /**
239     * Writes a trace message to indicate that the current method has ended.
240     * Must be called exactly once for each call to {@link #traceBegin} using the same tag.
241     *
242     * @param traceTag The trace tag.
243     *
244     * @hide
245     */
246    public static void traceEnd(long traceTag) {
247        if (isTagEnabled(traceTag)) {
248            nativeTraceEnd(traceTag);
249        }
250    }
251
252    /**
253     * Writes a trace message to indicate that a given section of code has
254     * begun. Must be followed by a call to {@link #asyncTraceEnd} using the same
255     * tag. Unlike {@link #traceBegin(long, String)} and {@link #traceEnd(long)},
256     * asynchronous events do not need to be nested. The name and cookie used to
257     * begin an event must be used to end it.
258     *
259     * @param traceTag The trace tag.
260     * @param methodName The method name to appear in the trace.
261     * @param cookie Unique identifier for distinguishing simultaneous events
262     *
263     * @hide
264     */
265    public static void asyncTraceBegin(long traceTag, String methodName, int cookie) {
266        if (isTagEnabled(traceTag)) {
267            nativeAsyncTraceBegin(traceTag, methodName, cookie);
268        }
269    }
270
271    /**
272     * Writes a trace message to indicate that the current method has ended.
273     * Must be called exactly once for each call to {@link #asyncTraceBegin(long, String, int)}
274     * using the same tag, name and cookie.
275     *
276     * @param traceTag The trace tag.
277     * @param methodName The method name to appear in the trace.
278     * @param cookie Unique identifier for distinguishing simultaneous events
279     *
280     * @hide
281     */
282    public static void asyncTraceEnd(long traceTag, String methodName, int cookie) {
283        if (isTagEnabled(traceTag)) {
284            nativeAsyncTraceEnd(traceTag, methodName, cookie);
285        }
286    }
287
288    /**
289     * Writes a trace message to indicate that a given section of code has begun. This call must
290     * be followed by a corresponding call to {@link #endSection()} on the same thread.
291     *
292     * <p class="note"> At this time the vertical bar character '|', newline character '\n', and
293     * null character '\0' are used internally by the tracing mechanism.  If sectionName contains
294     * these characters they will be replaced with a space character in the trace.
295     *
296     * @param sectionName The name of the code section to appear in the trace.  This may be at
297     * most 127 Unicode code units long.
298     */
299    public static void beginSection(String sectionName) {
300        if (isTagEnabled(TRACE_TAG_APP)) {
301            if (sectionName.length() > MAX_SECTION_NAME_LEN) {
302                throw new IllegalArgumentException("sectionName is too long");
303            }
304            nativeTraceBegin(TRACE_TAG_APP, sectionName);
305        }
306    }
307
308    /**
309     * Writes a trace message to indicate that a given section of code has ended. This call must
310     * be preceeded by a corresponding call to {@link #beginSection(String)}. Calling this method
311     * will mark the end of the most recently begun section of code, so care must be taken to
312     * ensure that beginSection / endSection pairs are properly nested and called from the same
313     * thread.
314     */
315    public static void endSection() {
316        if (isTagEnabled(TRACE_TAG_APP)) {
317            nativeTraceEnd(TRACE_TAG_APP);
318        }
319    }
320}
321