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